1 Alumnos del grupo:

Alumno Código Correo Porcentaje de Trabajo
Samir Stefano Suarez Rios 202210611 samir.suarez@utec.edu.pe x%
Milton Esteban Robles Reyes 202210416 milton.robles@utec.edu.pe x%
Caballito Hurtado 201610002 María.salinas@utec.edu.pe x%
Chriss Martin de Coldplay 201610002 María.salinas@utec.edu.pe x%

2 Tema

Análisis mensual de la relación entre número de pasajeros e ingresos totales por aeropuerto (2020-2022)

3 Objetivo

Evaluar la influencia del número de pasajeros en los ingresos totales ($) por mes y año en cada aeropuerto en el Perú.

3.1 Objetivo Secundarios

  • Determinar el aeropuerto con mayor afluencia de pasajeros y el de mayor ingresos del Perú.

  • Comparar los ingresos totales ($) de los rubros (T U U A Nacional, T U U A Internacional ) en los aeropuertos del Perú.

  • Comparar los ingresos totales ($) durante la pandemia y post pandemia en el Perú.

3.2 Tabla de variables

4 Librerías

5 Tablas

6 Limpieza de datos

6.1 Creando el DataFrame a partir de la variable Ingresos Totales (IT)

ITS <- filter(ITS, Año %in% c("2020","2021","2022"))
ITS %>% group_by(Año,Mes,Aeropuerto,Infraestructura) %>% summarise(IT = sum(`Importe por Servicios`)) -> DF
DF$IT[is.na(DF$IT)] <- 0

6.2 Uniendo la variable Ingresos Regulados (IR)

IRS %>% group_by(Año,Mes,Aeropuerto) %>% summarise(IR = sum(`Importe por Servicios`)) -> IRegulados
DF <- merge(DF, IRegulados, by = c("Año","Mes","Aeropuerto"), all=TRUE)
DF$IR[is.na(DF$IR)] <- 0

6.3 Uniendo la variable Numero de Pasajeros Internacionales (NPI)

PI <- filter(TP, `Tipo de Pasajero` == "INTERNACIONAL")
PI <- filter(PI,Año %in% c(2020,2021,2022))
PI <- select(PI, -Periodo)
PI <- select(PI, -`Tipo de Pasajero`)
DF <- merge(DF,PI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all = TRUE)
DF <- rename(DF, "NPI" = "Nro Pasajeros")
DF$NPI[is.na(DF$NPI)] <- 0

#Reemplazo de N/A's por 0

6.4 Uniendo la variable Numero de Pasajeros Nacionales (NPN)

PN <- filter(TP, `Tipo de Pasajero` == "NACIONAL")
PN <- filter(PN,Año %in% c(2020,2021,2022))
PN <- select(PN, -Periodo)
PN <- select(PN, -`Tipo de Pasajero`)
DF <- merge(DF,PN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "NPN" = "Nro Pasajeros")
DF$NPN[is.na(DF$NPN)] <- 0

#Reemplazo de N/A's por 0

6.5 Uniendo la variable Ingreso Rubro T U U A NACIONAL (TUUAN)

TUUAN <- filter(ITS, `Rubro Ingreso` == "T U U A NACIONAL")
TUUAN <- filter(TUUAN,Año %in% c(2020,2021,2022))
TUUAN <- select(TUUAN, -'Tipo Ingreso')
TUUAN <- select(TUUAN, -'Rubro Ingreso')
TUUAN <- select(TUUAN, -'Periodo')
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN_VER" = "Importe por Servicios")
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN" = "Importe por Servicios")
DF$TUUAN_VER[is.na(DF$TUUAN_VER)] <- 0
DF$TUUAN_VER[DF$TUUAN_VER != 0] <- "Si"
DF$TUUAN_VER[DF$TUUAN_VER == "0"] <- "No"
DF$TUUAN[is.na(DF$TUUAN)] <- 0
#Reemplazo de N/A's por 0

6.6 Uniendo la variable Ingreso Rubro T U U A INTERNACIONAL (TUUAI)

TUUAI <- filter(ITS, `Rubro Ingreso` == "T U U A INTERNACIONAL")
TUUAI <- filter(TUUAI,Año %in% c(2020,2021,2022))
TUUAI <- select(TUUAI, -'Tipo Ingreso')
TUUAI <- select(TUUAI, -'Rubro Ingreso')
TUUAI <- select(TUUAI, -'Periodo')
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI_VER" = "Importe por Servicios")#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI" = "Importe por Servicios")

DF$TUUAI_VER[is.na(DF$TUUAI_VER)] <- 0
DF$TUUAI_VER[DF$TUUAI_VER != 0] <- "Si"
DF$TUUAI_VER[DF$TUUAI_VER == "0"] <- "No"
DF$TUUAI[is.na(DF$TUUAI)] <- 0
#Reemplazo de N/A's por 0

6.7 Uniendo la variable Ingreso Rubro ATERRIZAJE Y DESPEGUE (IRAD)

IRAD <- filter(ITS, `Rubro Ingreso` == "ATERRIZAJE Y DESPEGUE")
IRAD <- filter(IRAD,Año %in% c(2020,2021,2022))
IRAD <- select(IRAD, -'Tipo Ingreso')
IRAD <- select(IRAD, -'Rubro Ingreso')
IRAD <- select(IRAD, -'Periodo')

DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD" = "Importe por Servicios")

DF$IRAD_VER[is.na(DF$IRAD_VER)] <- 0
DF$IRAD_VER[DF$IRAD_VER != 0] <- "Si"
DF$IRAD_VER[DF$IRAD_VER == "0"] <- "No"
DF$IRAD[is.na(DF$IRAD)] <- 0
#Reemplazo de N/A's por 0

6.8 Uniendo la variable Ingreso Rubro ALQUILER AREAS DE MANTENIMIENTO (AADM)

AADM <- filter(ITS, `Rubro Ingreso` == "ALQUILER AREAS DE MANTENIMIENTO")
AADM <- filter(AADM,Año %in% c(2020,2021,2022))
AADM <- select(AADM, -'Tipo Ingreso')
AADM <- select(AADM, -'Rubro Ingreso')
AADM <- select(AADM, -'Periodo')

DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM" = "Importe por Servicios")

DF$AADM_VER[is.na(DF$AADM_VER)] <- 0
DF$AADM_VER[DF$AADM_VER != 0] <- "Si"
DF$AADM_VER[DF$AADM_VER == "0"] <- "No"
DF$AADM[is.na(DF$AADM)] <- 0
#Reemplazo de N/A's por 0

6.9 Uniendo la variable Ingreso ALQUILER DE ESPACIOS PUBLICITSARIOS (ADEP)

ADEP <- filter(ITS, `Rubro Ingreso` == "ALQUILER DE ESPACIOS PUBLICITSARIOS")
ADEP <- filter(ADEP,Año %in% c(2020,2021,2022))
ADEP <- select(ADEP, -'Tipo Ingreso')
ADEP <- select(ADEP, -'Rubro Ingreso')
ADEP <- select(ADEP, -'Periodo')

DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP" = "Importe por Servicios")

DF$ADEP_VER[is.na(DF$ADEP_VER)] <- 0
DF$ADEP_VER[DF$ADEP_VER != 0] <- "Si"
DF$ADEP_VER[DF$ADEP_VER == "0"] <- "No"
DF$ADEP[is.na(DF$ADEP)] <- 0
#Reemplazo de N/A's por 0

6.10 Uniendo la variable Ingreso ALQUILER LOCALES COMERCIALES (ALC)

ALC <- filter(ITS, `Rubro Ingreso` == "ALQUILER LOCALES COMERCIALES")
ALC <- filter(ALC,Año %in% c(2020,2021,2022))
ALC <- select(ALC, -'Tipo Ingreso')
ALC <- select(ALC, -'Rubro Ingreso')
ALC <- select(ALC, -'Periodo')

DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC" = "Importe por Servicios")

DF$ALC_VER[is.na(DF$ALC_VER)] <- 0
DF$ALC_VER[DF$ALC_VER != 0] <- "Si"
DF$ALC_VER[DF$ALC_VER == "0"] <- "No"
DF$ALC[is.na(DF$ALC)] <- 0
#Reemplazo de N/A's por 0

6.11 Uniendo la variable Ingreso Rubro ALQUILER OFICINAS OPERACIONES AEROLÍNEAS (AOOA)

AOOA <- filter(ITS, `Rubro Ingreso` == "ALQUILER OFICINAS OPERACIONES AEROLÍNEAS")
AOOA <- filter(AOOA,Año %in% c(2020,2021,2022))
AOOA <- select(AOOA, -'Tipo Ingreso')
AOOA <- select(AOOA, -'Rubro Ingreso')
AOOA <- select(AOOA, -'Periodo')

DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA" = "Importe por Servicios")
DF$AOOA_VER[is.na(DF$AOOA_VER)] <- 0
DF$AOOA_VER[DF$AOOA_VER != 0] <- "Si"
DF$AOOA_VER[DF$AOOA_VER == "0"] <- "No"
DF$AOOA[is.na(DF$AOOA)] <- 0

6.12 Uniendo la variable Ingreso Rubro ALQUILERES DE ALMACEN/HANGAR (ADAH)

ADAH <- filter(ITS, `Rubro Ingreso` == "ALQUILERES DE ALMACEN/HANGAR")
ADAH <- filter(ADAH,Año %in% c(2020,2021,2022))
ADAH <- select(ADAH, -'Tipo Ingreso')
ADAH <- select(ADAH, -'Rubro Ingreso')
ADAH <- select(ADAH, -'Periodo')

DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH" = "Importe por Servicios")
DF$ADAH_VER[is.na(DF$ADAH_VER)] <- 0
DF$ADAH_VER[DF$ADAH_VER != 0] <- "Si"
DF$ADAH_VER[DF$ADAH_VER == "0"] <- "No"
DF$ADAH[is.na(DF$ADAH)] <- 0

6.13 Uniendo la variable Ingreso Rubro ATENCIÓN EN HORAS EXTRAS (AEHE)

AEHE <- filter(ITS, `Rubro Ingreso` == "ATENCIÓN EN HORAS EXTRAS")
AEHE <- filter(AEHE,Año %in% c(2020,2021,2022))
AEHE <- select(AEHE, -'Tipo Ingreso')
AEHE <- select(AEHE, -'Rubro Ingreso')
AEHE <- select(AEHE, -'Periodo')

DF <- merge(DF, AEHE, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AEHE_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, AEHE, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AEHE" = "Importe por Servicios")
DF$AEHE_VER[is.na(DF$AEHE_VER)] <- 0
DF$AEHE_VER[DF$AEHE_VER != 0] <- "Si"
DF$AEHE_VER[DF$AEHE_VER == "0"] <- "No"
DF$AEHE[is.na(DF$AEHE)] <- 0

6.14 Uniendo la variable Ingreso Rubro ESTACIONAMIENTO AERONAVES (IREA)

IREA <- filter(ITS, `Rubro Ingreso` == "ESTACIONAMIENTO AERONAVES")
IREA <- filter(IREA,Año %in% c(2020,2021,2022))
IREA <- select(IREA, -'Tipo Ingreso')
IREA <- select(IREA, -'Rubro Ingreso')
IREA <- select(IREA, -'Periodo')

DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA" = "Importe por Servicios")
DF$IREA_VER[is.na(DF$IREA_VER)] <- 0
DF$IREA_VER[DF$IREA_VER != 0] <- "Si"
DF$IREA_VER[DF$IREA_VER == "0"] <- "No"
DF$IREA[is.na(DF$IREA)] <- 0

6.15 Uniendo la variable Ingreso Rubro INGRESOS FINANCIEROS (IRIF)

IRIF <- filter(ITS, `Rubro Ingreso` == "INGRESOS FINANCIEROS")
IRIF <- filter(IRIF,Año %in% c(2020,2021,2022))
IRIF <- select(IRIF, -'Tipo Ingreso')
IRIF <- select(IRIF, -'Rubro Ingreso')
IRIF <- select(IRIF, -'Periodo')

DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF" = "Importe por Servicios")
DF$IRIF_VER[is.na(DF$IRIF_VER)] <- 0
DF$IRIF_VER[DF$IRIF_VER != 0] <- "Si"
DF$IRIF_VER[DF$IRIF_VER == "0"] <- "No"
DF$IRIF[is.na(DF$IRIF)] <- 0

6.16 Uniendo la variable Ingreso Rubro REEMBOLSOS (IRR)

IRR <- filter(ITS, `Rubro Ingreso` == "REEMBOLSOS")
IRR <- filter(IRR,Año %in% c(2020,2021,2022))
IRR <- select(IRR, -'Tipo Ingreso')
IRR <- select(IRR, -'Rubro Ingreso')
IRR <- select(IRR, -'Periodo')

IRR <- filter(IRR, `Importe por Servicios` != 0)

DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's 
DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR" = "Importe por Servicios")
DF$IRR_VER[is.na(DF$IRR_VER)] <- 0
DF$IRR_VER[DF$IRR_VER != 0] <- "Si"
DF$IRR_VER[DF$IRR_VER == "0"] <- "No"
DF$IRR[is.na(DF$IRR)] <- 0

6.17 Agregando la variable Numero de Pasajeros Totales (NP)

DF %>% mutate(NP = NPN + NPI) -> DF
#Numero de pasajeros totales

6.18 Eliminación de datos y arreglos

# Si es que no tenemos el nombre del aeropuerto o su infraestructura (Siempre debe venir acompañada del nombre), la unidad muestral no podrá entrar al análisis pues por ejemplo si nos dicen cuanto gano un aeropuerto desconocido, esto no nos dirá nada.


DF$Mes = factor(DF$Mes, levels =c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Setiembre","Octubre","Noviembre","Diciembre"))
DF <- arrange(DF, Año, Mes)

DF$Aeropuerto[DF$Aeropuerto == 'No precisa'] <- NA
DF$Aeropuerto[DF$Aeropuerto == '-'] <- NA
DF$Infraestructura[DF$Infraestructura == '-'] <- NA

DF <- filter(DF, Infraestructura != is.na("Infraestructura") & Aeropuerto != is.na("Aeropuerto"))

DF %>% mutate("Entidad_Infraestructura" =
                  ifelse(Infraestructura=="ADP", "Aeropuertos del Perú S.A.",
                  ifelse(Infraestructura=="AAP", "Aeropuertos Andinos del Perú S.A.",
                  ifelse(Infraestructura=="COR", "CORPAC S.A.",
                  ifelse(Infraestructura=="LAP", "Lima Airport Partners S.R.L.",Infraestructura))))) -> DF
sum(complete.cases(DF))
[1] 378

DF$Mes = factor(DF$Mes, levels =c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Setiembre","Octubre","Noviembre","Diciembre"))
DF <- arrange(DF, Año, Mes)

6.19 Exportando la base de datos

write_csv(DF,"BaseLimpiav2.csv")

7 Importando la base datos limpia


rm(list = ls())
library(readr)
library(plyr)
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:plyr’:

    arrange, count, desc, failwith, id, mutate, rename, summarise, summarize

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(plotrix)
library(ggplot2)
library(stringi)
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following objects are masked from ‘package:plyr’:

    arrange, mutate, rename, summarise

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(MASS)

Attaching package: ‘MASS’

The following object is masked from ‘package:plotly’:

    select

The following object is masked from ‘package:dplyr’:

    select
DF <- read_csv("BaseLimpiav2.csv")
Rows: 1148 Columns: 34── Column specification ───────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (16): Mes, Aeropuerto, Infraestructura, TUUAN_VER, TUUAI_VER, IRAD_VER, AADM_VER, ADEP_VER, ALC_VER...
dbl (18): Año, IT, IR, NPI, NPN, TUUAN, TUUAI, IRAD, AADM, ADEP, ALC, AOOA, ADAH, AEHE, IREA, IRIF, IRR...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

8 Variables

Año: Variable categórica que indica el año de la recolección de información.

Mes: Variable categórica que indica el mes de la recolección de información.

Aeropuerto: Variable cualitativa que indica el aeropuerto del cual se recolecta la información

Infraestructura: Variable cualitativa que indica en acrónimo a que entidad pertenece la infraestructura del aeropuerto del cual se recolecta la información.

Entidad_Infraestructura: Variable cualitativa que indica a que entidad pertenece la infraestructura del aeropuerto del cual se recolecta la información.

IT: Variable cuantitativa que representa los ingresos totales en dolares que ha registrado el aeropuerto

IR: Variable cuantitativa que representa los ingresos regulados en dolares que ha registrado el aeropuerto

TUUAN: Variable cuantitativa que representa el ingreso en dolares que ha generado la TARIFA UNIFICADA POR USO DE AEROPUERTO de tipo nacional.

TUUAN: Variable cuantitativa que representa el ingreso en dolares que ha generado la TARIFA UNIFICADA POR USO DE AEROPUERTO de tipo internacional.

NPI: Variable cuantitativa que representa el numero de pasajeros internacionales que ha registrado el aeropuerto

NPN: Variable cuantitativa que representa el numero de pasajeros nacionales que ha registrado el aeropuerto

IRAD_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por aterrizaje y despegue.

IRAD: Variable cuantitativa que representa el ingreso en dolares del aeropuerto por aterrizaje y despegue.

AADM_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el alquiler de áreas de mantenimiento.

AADM: Variable cuantitativa que representa el ingreso en dolares por el alquiler de áreas de mantenimiento.

ADEP_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el alquiler de espacios de publicidad.

ADEP: Variable cuantitativa que representa el ingreso en dolares por el alquiler de espacios de publicidad.

ALC_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el alquiler de locales comerciales.

ALC: Variable cuantitativa que representa el ingreso en dolares por el alquiler de locales comerciales.

AOOA_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el alquiler de oficinas de operaciones de aerolíneas.

AOOA: Variable cuantitativa que representa el ingreso en dolares por el alquiler de oficinas de operaciones de aerolíneas.

ADAH_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el alquiler de almacenes/hangares.

ADAH: Variable cuantitativa que representa el ingreso en dolares por el alquiler de almacenes/hangares.

AEHE_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por la atención en horas extras.

AEHE: Variable cuantitativa que representa el ingreso en dolares por la atención en horas extras.

IREA_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por el estacionamiento de aeronaves.

IREA: Variable cuantitativa que representa el ingreso en dolares por el estacionamiento de aeronaves.

IRIF_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por reembolso en ingresos financieros.

IRIF: Variable cuantitativa que representa el ingreso en dolares por reembolso en ingresos financieros.

IRR_VER: Variable categórica que representa si el aeropuerto obtiene ingresos por reembolsos.

IRR: Variable cuantitativa que representa el ingreso en dolares por reembolsos.

NP: Variable cuantitativa que representa el numero de pasajeros totales que ha registrado el aeropuerto.

9 Descriptores Numéricos

cv <- function(x){
    return(sd(x, na.rm=T)/mean(x, na.rm=T))
}
tabla <- data.frame(Variables = c('IT', 'NPN', 'NPI', 'TUUAN','TUUAI'),
                    Media = c(mean(DF$IT, na.rm=T), 
                              mean(DF$NPN, na.rm = T), 
                              mean(DF$NPI, na.rm= T),
                              mean(DF$TUUAN, na.rm= T),
                              mean(DF$TUUAI, na.rm= T)),
                    
                    Mediana = c(median(DF$IT, na.rm=T), 
                                median(DF$NPN, na.rm = T), 
                                median(DF$NPI, na.rm= T),
                                median(DF$TUUAN, na.rm = T), 
                                median(DF$TUUAI, na.rm= T)), 
                    
                    Desviacion = c(sd(DF$IT, na.rm=T), 
                                   sd(DF$NPN, na.rm = T), 
                                   sd(DF$NPI, na.rm= T), 
                                   sd(DF$TUUAN, na.rm = T), 
                                   sd(DF$TUUAI, na.rm= T)), 
                    
                    Varianza = c(var(DF$IT, na.rm = T), 
                                 var(DF$NPN, na.rm = T), 
                                 var(DF$NPI, na.rm = T), 
                                 var(DF$TUUAN, na.rm = T), 
                                 var(DF$TUUAI, na.rm = T)),
                    
                    RangoIntercuartil = c(IQR(DF$IT, na.rm = T), 
                                        IQR(DF$NPN, na.rm = T), 
                                        IQR(DF$NPI, na.rm = T), 
                                        IQR(DF$TUUAN, na.rm = T), 
                                        IQR(DF$TUUAI, na.rm = T)),
                    
                    CoeficienteVariacion = c(cv(DF$IT), 
                                 cv(DF$NPN), 
                                 cv(DF$NPI),
                                 cv(DF$NPN), 
                                 cv(DF$NPI)))
tabla

De la tabla podemos conseguir la siguiente información:

  • La escala con la que se trabaja es bastante grande, de ahí el hecho que la varianza y desviación sean tan grande.

  • Tanto la varianza como la desviación nos indican que los datos de los Ingresos Totales, el Numero de Pasajeros Nacionales y el Numero de Pasajeros Internacionales están muy dispersos.

  • Se aprecia un fenómeno que la mediana y el rango intercuartil de la variable Pasajeros internacionales es 0. Esto quiere decir que hay muchos aeropuertos los cuales no suelen recibir pasajeros internacionales.

10 Descriptores Gráficos

10.1 Numero de Pasajeros vs Ingresos Totales

plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))

Comenzamos comparando el numero de pasajeros en miles totales, suma de pasajeros internacionales y nacionales, con los ingresos totales de cada aeropuerto en determinado mes y año en millones de dolares. A simple vista se puede ver un cierto tipo de relación lineal, sin embargo tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que este no toma en cuenta la escala de las unidades, perfecto para nuestro estudio.

cor(DF$IT, DF$NP, use="complete.obs")
[1] 0.9834118

Con la información suministrada del coeficiente de correlación se deduce que la relación lineal entre el numero de pasajeros y los ingresos totales es buena, casi perfecta y ascendente. Es decir los ingresos totales aumentaran en cuanto aumente el numero de pasajeros.

Ahora crearemos un modelo de regresión lineal.


modelo = lm(DF$IT ~ DF$NP, data=DF)
modelo

Call:
lm(formula = DF$IT ~ DF$NP, data = DF)

Coefficients:
(Intercept)        DF$NP  
 -151042.68        16.46  
d <- data.frame("X"=DF$NP/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
   -0.15104      0.01646  

Hemos creado dos modelos que en realidad son el mismo pero a diferentes escalas. El primero nos sirve para usar directamente el numero de pasajeros y los ingresos totales en dolares. El segundo para usar el numero de pasajeros en miles y conseguir los ingresos totales en millones de dolares. Ambos modelos nos permiten aproximar, predecir los ingresos totales de un aeropuerto en determinado mes y año usando la cantidad de pasajeros totales que llevo en el mismo lapso de tiempo.

plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))
abline(a= -0.14890, b=0.01646, col="green")

10.2 Numero de Pasajeros Nacionales e Internacionales vs Ingresos Totales

par(mfrow=c(1,2))

plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")

plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")

Ahora vamos a analizar la relación de los tipos de pasajeros con los ingresos totales. De nuevo usaremos el coeficiente de correlación tanto para los pasajeros nacionales como internacionales.

cor(DF$IT, DF$NPN, use="complete.obs")
[1] 0.9738777
cor(DF$IT, DF$NPI, use="complete.obs")
[1] 0.9783331

De los coeficientes dados se encuentra que:

  • Ambos demuestran que tanto los pasajeros nacionales como internacionales poseen una buena y ascendente relación lineal con los ingresos totales.
  • Ambos son menores al cor de los pasajeros totales con los ingresos totales. Indica que si se usa solo a los pasajeros nacionales o solo a los internacionales para aproximar los ingresos totales, se tendrá una precisión menor a que si se usará la suma de ambos.
  • El cor de los pasajeros internacionales es ligeramente superior al de los pasajeros nacionales, mostrando que su relación lineal con los ingresos totales es ligeramente más acorde que la relación lineal de los pasajeros nacionales.

Ahora construyamos los modelos de regresión lineal para cada uno.


modelo = lm(DF$IT ~ DF$NPN, data=DF)
modelo

Call:
lm(formula = DF$IT ~ DF$NPN, data = DF)

Coefficients:
(Intercept)       DF$NPN  
 -363490.18        24.52  
d <- data.frame("X"=DF$NPN/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
   -0.36349      0.02452  
modelo = lm(DF$IT ~ DF$NPI, data=DF)
modelo

Call:
lm(formula = DF$IT ~ DF$NPI, data = DF)

Coefficients:
(Intercept)       DF$NPI  
  319864.95        47.72  
d <- data.frame("X"=DF$NPI/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
    0.31986      0.04772  
rm(d)

Vemos que los modelos difieren en una cantidad considerable en cuanto a su pendiente, sin embargo, su intercepto es bastante similar, vamos a graficar estos modelos.

par(mfrow=c(1,2))

plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")
abline(a= -0.36033, b=0.02451, col="#f72585")

plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")
abline(a= 0.31996, b=0.04772, col="#0077b6")

10.3 Analizando la distribución de Ingresos Totales

plot_ly(x = ~DF$IT/1000000,
        type="histogram",
        color = ~DF$Infraestructura,
        nbinsx = 100
        )%>%
layout(yaxis = list( title = "Frecuencia" ),
    xaxis = list( title = "Ingresos totales (Millones de US$)",
                  nticks = 20))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations

Gracias al histograma se dice que los datos de los ingresos totales son totalmente asimétricos y se encuentran acumulados en un intervalo de 0 - 0.5 millones de dolares. Es decir la mayoría de aeropuertos determinados en cierto mes y cierto año posee unos ingresos totales de entre 0 y 0.5 millones de dolares. Esto puede ocurrir debido a datos atípicos, construyamos un Boxplot para que nos ayude.

plot_ly(DF, x=~DF$IT/1000000,
            type = "box")%>%
layout(
    xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations

Usando un Boxplot simple se comprueba como los datos de los ingresos totales están demasidos dispersos gracias a cierta cantidad de datos atipicos. Ahora es necesario averiguar de donde provienen estos datos atípicos y que nos quieren decir. Para ello crearemos diferentes Boxplots basados en meses, infraestructuras y aeropuertos.

plot_ly(DF, x = ~IT/1000000, 
        y = ~Mes, 
        color= ~Mes, 
        type="box") %>%
layout(yaxis = list( title = "Mes"),
    xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Con este gráfico podemos descartar que los datos atípicos provengan de un o varios meses en específico.

plot_ly(DF, x = ~IT/1000000, 
        y = ~Infraestructura, 
        color= ~Entidad_Infraestructura, 
        type="box") %>%
layout(yaxis = list( title = "Infraestructura"),
    xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations

En este gráfico se observa como Lima Airport Partners S.R.L rebasa por mucho a las otras infraestructuras en cuanto a ingresos totales se refiere. Aquí podemos ya saber que esos datos atípicos de ingresos están generados en su gran mayoría por la infraestructura Lima Airport Partners S.R.L. Además es importante mencionar que la infraestructura COR no aparece en la gráfica pues no ha declarado ningún ingreso total.

plot_ly(DF, x = ~IT/1000000, 
        y = ~Aeropuerto, 
        color= ~Aeropuerto, 
        type="box"
        ) %>%
layout(yaxis = list( title = "Aeropuertos"),
    xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Gracias a los 3 gráficos podemos concluir que:

  • El aeropuerto de Lima cuya entidad prestadora es la LAP, es la responsable de los datos atípicos y además es el que más ingresos totales genera.
  • La infraestructura LAP trabaja en Lima y se refiere al Aeropuerto Internacional Jorge Chávez. Esto nos quiere decir que en el Perú, el aeropuerto que genera más ingresos es el Jorge Chávez.

10.4 Numero de Pasajeros vs Aeropuertos

plot_ly(DF,y = ~NP/1000,
        x = ~as.factor(Aeropuerto), 
        type="bar",
        marker = list(color=c("lightblue"))
        )%>%
    layout(xaxis = list( title = "Aeropuertos"),
    yaxis = list( title = "Numero de pasajeros (miles)"))

Con esta gráfico se corrobora que el Aeropuerto de Lima (Aeropuerto Internacional Jorge Chávez) genera la mayor cantidad de ingresos y además recibe a la mayor cantidad de pasajeros respecto al resto del Perú. Otros aeropuertos notables son Cusco, Arequipa e Iquitos donde Cusco es el que más pasajeros recibe fuera de Lima. Se procede a dibujar el numero de pasajeros, los ingresos totales y los aeropuertos.

plot_ly(DF,x = ~NP/1000,
        y = ~IT/1000000, 
        type="scatter",
        color = ~as.factor(Aeropuerto)
        )
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

El gráfico nos deja en claro la estrecha relación de la cantidad de pasajeros con la de ingresos que posee el aeropuerto de Lima y como este sobresale por mucho del resto de aeropuertos. Se concluye que los datos atípicos provenientes de ingresos totales eran y nos contaban sobre las peculiaridades del caso Lima.

10.5 Ingresos T U U A Total vs Ingresos Totales

Se eligió la comparación de las T U U A, porque esta es la TARIFA UNIFICADA POR USO DE AEROPUERTO, es decir es una tarifa que como consumidores debemos de pagar. El objetivo aquí es analizar cuanto de los ingresos totales provienen directamente de los bolsillos de los pasajeros.

plot((DF$TUUAN/1000000 + DF$TUUAI/1000000), DF$IT/1000000, xlab = "Ingresos por TUUA (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")

Comenzamos comparando el numero de pasajeros en miles totales, suma de pasajeros internacionales y nacionales, con los ingresos totales de cada aeropuerto en determinado mes y año en millones de dolares. A simple vista se puede ver un cierto tipo de relación lineal, sin embargo tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que este no toma en cuenta la escala de las unidades, perfecto para nuestro estudio.

cor(DF$IT, DF$TUUAI + DF$TUUAN, use="complete.obs")
[1] 0.9870129

Tenemos un coeficiente de correlación que esta muy próximo a 1, es decir esta relación es casi perfectamente lineal y con tendencia ascendente.

Ahora crearemos un modelo de regresión lineal.

TUUA <- DF$TUUAI+DF$TUUAN
modelo = lm(DF$IT ~ TUUA, data=DF)
modelo

Call:
lm(formula = DF$IT ~ TUUA, data = DF)

Coefficients:
(Intercept)         TUUA  
  155740.38         2.19  
d <- data.frame("X"= (DF$TUUAI + DF$TUUAN)/100000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
     0.1557       0.2190  
rm(d)

Del modelo creado se obtiene el intercepto, es decir cuando la TUUA valdrá cero y la pendiente, en este caso es relativamente baja pero ascendente.

plot(TUUA/100000, DF$IT/1000000, xlab = "TUUA total (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")
abline(a= 0.1557, b=0.2190, col="#c9a227")

10.6 Ingresos TUUA Nacional y TUUA Internacional vs Ingresos Totales

par(mfrow=c(1,2))

plot(DF$TUUAN/1000000, DF$IT/1000000, xlab = "Ingresos TUUA nacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#f8961e", pch="•")

plot(DF$TUUAI/1000000, DF$IT/1000000, xlab = "Ingresos TUUA internacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#90be6d", pch="•")

Probemos de nuevo a usar el coeficiente de correlación para ambas variables

cor(DF$IT, DF$TUUAN, use="complete.obs")
[1] 0.985771
cor(DF$IT, DF$TUUAI, use="complete.obs")
[1] 0.9760972

De los coeficientes dados se encuentra que:

  • Los dos coeficientes muestran una casi perfecta linealidad ascendente.
  • Ninguno de los dos cor por separado pudo superar al anterior visto producto de la suma de las TUUA.
  • El cor nacional es ligeramente superior al cor internacional.

Ahora construyamos los modelos de regresión lineal para cada uno.


modelo = lm(DF$IT ~ DF$TUUAN, data=DF)
modelo

Call:
lm(formula = DF$IT ~ DF$TUUAN, data = DF)

Coefficients:
(Intercept)     DF$TUUAN  
 -59899.076        5.213  
d <- data.frame("X"=DF$TUUAN/1000000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
    -0.0599       5.2126  
modelo = lm(DF$IT ~ DF$TUUAI, data=DF)
modelo

Call:
lm(formula = DF$IT ~ DF$TUUAI, data = DF)

Coefficients:
(Intercept)     DF$TUUAI  
  3.295e+05    3.688e+00  
d <- data.frame("X"=DF$TUUAI/1000000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo

Call:
lm(formula = d$Y ~ d$X, data = d)

Coefficients:
(Intercept)          d$X  
     0.3295       3.6882  
rm(d)

Los modelos poseen bastantes diferencias entre sí como sus interceptos que a simple no tienen nada en común al igual que sus pendientes. Veamoslo en una grafica.

par(mfrow=c(1,2))

plot(DF$TUUAN/1000000, DF$IT/1000000, xlab = "Ingresos TUUA nacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#f8961e", pch="•")
abline(a= -0.0599, b=5.2126, col="#f3722c")

plot(DF$TUUAI/1000000, DF$IT/1000000, xlab = "Ingresos TUUA internacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#90be6d", pch="•")
abline(a= 0.3295, b=3.6882, col="#43aa8b")

Detallamos entonces que los ingresos totales guardan una alta relación con los ingresos generados por las TUUA y dependen en gran medida de estas, ergo la cantidad de pasajeros.

10.7 Pandemia vs PostPandemia

DF2020 <- filter(DF, DF$Año=="2020")
DF2021 <- filter(DF, DF$Año=="2021")
DF2022 <- filter(DF, DF$Año=="2022")

DF2020 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2020
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
DF2021 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2021
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
                                           
DF2022 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2022
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
plot_ly(y = ~DF2020$IT/1000000,
        x = ~DF2020$Mes, 
        type="bar",
        name="2020",
        marker = list(color = '#57cc99')
        )%>% 

    
    add_trace(y = ~DF2021$IT/1000000,
        x = ~DF2021$Mes, 
        type="bar",
        name="2021",
        marker = list(color = '#38a3a5')
        )%>%
    
    
    add_trace(y = ~DF2022$IT/1000000,
        x = ~DF2022$Mes, 
        type="bar",
        name="2022",
        marker = list(color = '#22577a')
        )%>%
    
    
    layout(xaxis = list( title = "Meses"),
    yaxis = list( title = "Ingresos totales (Millones de US$)",
    nticks = 10,
    range = list(0,45)),
    
    barmode="group")

Del gráfico de barras podemos observar:

  • La distribución de los ingresos totales en base a los meses del año.

  • Existe una asimetria notable entre los datos en el año 2020. Esta asimetria se explica por el surgimiento del Covid-19. Los ingresos bajaron bastante en proporción a la media.

  • Un patrón de crecimiento sobre los ingresos totales dependiendo de los meses. En algunos meses los ingresos totales son esperado a ser mayores que en otros meses, uno de los factores que pueden influir en esto son las vacaciones pues están estrechamente relacionas con el número de pasajeros a abordarr en un aeropuerto.


plot_ly() %>%
    add_trace(y = ~DF2020$IT/1000000,
        x = ~DF2020$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2020",
        marker = list(color = '#57cc99'),
        line = list(color = '#57cc99'),
        fill = "tonexty",
        fillcolor = 'rgba(197,237,211,0.3)'
        )%>%
    add_trace(DF2021, y = ~DF2021$IT/1000000,
        x = ~DF2021$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2021",
        marker = list(color = '#38a3a5'),
        line = list(color = '#38a3a5'),
        fill = "tonexty",
        fillcolor = 'rgba(106,166,169,0.3)'
        )%>%
    add_trace(y = ~DF2022$IT/1000000,
        x = ~DF2022$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2022",
        marker = list(color = '#22577a'),
        line = list(color = '#22577a'),
        fill = "tonexty",
        fillcolor = 'rgba(68,102,122,0.3)'
        )%>%
    
    layout(xaxis = list( title = "Meses"),
           title = "Evolutivo Ingresos",
    yaxis = list( title = "Ingresos totales (Millones de US$)", 
                  range = list(0,45))
    )
NA
plot_ly() %>%
    add_trace(y = ~DF2020$NP/1000,
        x = ~DF2020$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2020",
        marker = list(color = '#E09F3E'),
        line = list(color = '#E09F3E'),
        fill = "tonexty",
        fillcolor = 'rgba(225,183,123,0.3)'
        )%>%
    add_trace(DF2021, y = ~DF2021$NP/1000,
        x = ~DF2021$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2021",
        marker = list(color = '#9E2A2B'),
        line = list(color = '#9E2A2B'),
        fill = "tonexty",
        fillcolor = 'rgba(158,72,74,0.3)'
        )%>%
    add_trace(y = ~DF2022$NP/1000,
        x = ~DF2022$Mes, 
        type="scatter",
        mode="lines+markers",
        name="2022",
        marker = list(color = '#540B0E'),
        line = list(color = '#540B0E'),
        fill = "tonexty",
        fillcolor = 'rgba(87,45,47,0.3)'
        )%>%
    
    layout(xaxis = list( title = "Meses"),
           title = "Evolutivo Pasajeros",
    yaxis = list( title = "Numero de Pasajeros (Miles)"))

De los gráficos evolutivos podemos apreciar:

  • Como es el comportamiento de los ingresos totales frente a los meses y a los años marcados por la pandemia.

  • En el mes de Febrero del año 2020 comienza una caída drástica en los ingresos hasta Abril del mismo año donde comienza a estabilizarse. Este periodo coincide con la aparición del Covid-19 en Perú y el establecimiento de las medidas de confinamiento. El confinamiento indica que el número de pasajeros se reduce en gran proporción. Esta causa también se puede observar en el evolutivo de pasajeros y el como su número de cae hasta 0 o casi 0. Los aeropuerto tuvieron consecuencias que tardaron mucho en disiparse Muestra de ello es como se tardó 2 años y 5 meses para volver a un punto similar al de Febrero 2020 en ingresos totales.

```r

round(100 - ((filter(DF2020, Mes == "Abril")$IT/1000000 )/( filter(DF2020, Mes == "Febrero")$IT/1000000) * 100) ,2)
```
```
[1] 86.68
```
```r
round( - filter(DF2020, Mes == "Abril")$IT/1000000  + filter(DF2020,Mes == "Febrero")$IT/1000000, 2)
```
```
[1] 31.67
```
  • La pérdida del mes de Abril del 2020 respecto al mes de Febrero del 2020 fue del 86.68% suponiendo una diferencia de 31.76 millones de dolares.

  • A partir del mes de Abril se estabilizan los ingresos del año 2020. Estos son bajos pero se observa una tendencia ascendente. Tendencia que continua en los años 2021 y 2022 a medida que el confinamiento se levanta, la pandemia se controla y el numero de pasajeros aumenta.

10.8 Conclusión

A razón de resumen, en nuestro análisis sobre la relación entre el número de pasajeros y los ingresos totales de los aeropuertos graficamos la distribución de los ingresos totales, las diferentes relaciones entre variables tales como la última vista (Ingresos TUUA vs Ingresos Totales), (cantidad de pasajeros y aeropuertos). Asimismo observamos y describimos el comportamiento evolutivo de los ingresos totales respecto a los años vividos en pandemia y post-pandemia. Finalemnte, con la información recolectada y el estudio realizado se encontró que los ingresos totales generados por los aeropuertos en el Perú dependente altamente en los consumidores o pasajeros, siendo la TUUA el ejemplo más claro de ello.

LS0tDQp0aXRsZTogIkVzdGFkaXN0aWNhcyBzb2JyZSBsb3MgYWVyb3B1ZXJ0b3MiDQphdXRob3I6ICJHcnVwbyA3LCBTZWNjacOzbiA5Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIg0KZWRpdG9yOiB2aXN1YWwNCmZvcm1hdDogaHRtbA0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQojICoqQWx1bW5vcyBkZWwgZ3J1cG86KioNCg0KfCBBbHVtbm8gICAgICAgICAgICAgICAgICAgICAgICAgIHwgKipDw7NkaWdvKiogICAgfCAqKkNvcnJlbyoqICAgICAgICAgICAgICAgICAgICAgfCAqKlBvcmNlbnRhamUgZGUgVHJhYmFqbyoqIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgKioqU2FtaXIgU3RlZmFubyBTdWFyZXogUmlvcyoqKiB8ICoqMjAyMjEwNjExKiogfCAqKnNhbWlyLnN1YXJlelxAdXRlYy5lZHUucGUqKiAgfCAqKnglKiogICAgICAgICAgICAgICAgICAgIHwNCnwgKipNaWx0b24gRXN0ZWJhbiBSb2JsZXMgUmV5ZXMqKiB8ICoqMjAyMjEwNDE2KiogfCAqKm1pbHRvbi5yb2JsZXNcQHV0ZWMuZWR1LnBlKiogfCAqKnglKiogICAgICAgICAgICAgICAgICAgIHwNCnwgKipDYWJhbGxpdG8gSHVydGFkbyoqICAgICAgICAgICB8ICoqMjAxNjEwMDAyKiogfCAqKk1hcsOtYS5zYWxpbmFzXEB1dGVjLmVkdS5wZSoqIHwgKip4JSoqICAgICAgICAgICAgICAgICAgICB8DQp8ICoqQ2hyaXNzIE1hcnRpbiBkZSBDb2xkcGxheSoqICAgfCAqKjIwMTYxMDAwMioqIHwgKipNYXLDrWEuc2FsaW5hc1xAdXRlYy5lZHUucGUqKiB8ICoqeCUqKiAgICAgICAgICAgICAgICAgICAgfA0KDQojICoqVGVtYSoqDQoNCkFuw6FsaXNpcyBtZW5zdWFsIGRlIGxhIHJlbGFjacOzbiBlbnRyZSBuw7ptZXJvIGRlIHBhc2FqZXJvcyBlIGluZ3Jlc29zIHRvdGFsZXMgcG9yIGFlcm9wdWVydG8gKDIwMjAtMjAyMikNCg0KIyAqKk9iamV0aXZvKioNCg0KRXZhbHVhciBsYSBpbmZsdWVuY2lhIGRlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBlbiBsb3MgaW5ncmVzb3MgdG90YWxlcyAoXCQpIHBvciBtZXMgeSBhw7FvIGVuIGNhZGEgYWVyb3B1ZXJ0byBlbiBlbCBQZXLDui4NCg0KIyMgT2JqZXRpdm8gU2VjdW5kYXJpb3MNCg0KLSAgIERldGVybWluYXIgZWwgYWVyb3B1ZXJ0byBjb24gbWF5b3IgYWZsdWVuY2lhIGRlIHBhc2FqZXJvcyB5IGVsIGRlIG1heW9yIGluZ3Jlc29zIGRlbCBQZXLDui4NCg0KLSAgIENvbXBhcmFyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIChcJCkgZGUgbG9zIHJ1YnJvcyAoVCBVIFUgQSBOYWNpb25hbCwgVCBVIFUgQSBJbnRlcm5hY2lvbmFsICkgZW4gbG9zIGFlcm9wdWVydG9zIGRlbCBQZXLDui4NCg0KLSAgIENvbXBhcmFyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIChcJCkgZHVyYW50ZSBsYSBwYW5kZW1pYSB5IHBvc3QgcGFuZGVtaWEgZW4gZWwgUGVyw7ouDQoNCiMjIFRhYmxhIGRlIHZhcmlhYmxlcw0KDQojIExpYnJlcsOtYXMNCg0KYGBge3IgZWNobz1GQUxTRX0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0Kcm0obGlzdD1scygpKQ0KYGBgDQoNCiMgVGFibGFzDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpJVFMgPC0gcmVhZF9jc3YoIlJlY2F1ZGFjaW9uSW5ncmVzb3NUb3RhbGVzLmNzdiIpDQpJUlM8LSByZWFkX2NzdigiUmVjYXVkYWNpb25JbmdyZXNvc1JlZ3VsYWRvcy5jc3YiKQ0KVFAgPC0gcmVhZF9jc3YoIlRyYWZpY29QYXNhamVyb3MuY3N2IikNCmBgYA0KDQojIExpbXBpZXphIGRlIGRhdG9zDQoNCiMjIENyZWFuZG8gZWwgRGF0YUZyYW1lIGEgcGFydGlyIGRlIGxhIHZhcmlhYmxlIEluZ3Jlc29zIFRvdGFsZXMgKElUKQ0KDQpgYGB7ciBldmFsPVRSVUV9DQpJVFMgPC0gZmlsdGVyKElUUywgQcOxbyAlaW4lIGMoIjIwMjAiLCIyMDIxIiwiMjAyMiIpKQ0KSVRTICU+JSBncm91cF9ieShBw7FvLE1lcyxBZXJvcHVlcnRvLEluZnJhZXN0cnVjdHVyYSkgJT4lIHN1bW1hcmlzZShJVCA9IHN1bShgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCkpIC0+IERGDQoNCmBgYA0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KREYkSVRbaXMubmEoREYkSVQpXSA8LSAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvcyBSZWd1bGFkb3MgKElSKQ0KDQpgYGB7cn0NCklSUyAlPiUgZ3JvdXBfYnkoQcOxbyxNZXMsQWVyb3B1ZXJ0bykgJT4lIHN1bW1hcmlzZShJUiA9IHN1bShgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCkpIC0+IElSZWd1bGFkb3MNCkRGIDwtIG1lcmdlKERGLCBJUmVndWxhZG9zLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiksIGFsbD1UUlVFKQ0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpERiRJUltpcy5uYShERiRJUildIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIE51bWVybyBkZSBQYXNhamVyb3MgSW50ZXJuYWNpb25hbGVzIChOUEkpDQoNCmBgYHtyfQ0KUEkgPC0gZmlsdGVyKFRQLCBgVGlwbyBkZSBQYXNhamVyb2AgPT0gIklOVEVSTkFDSU9OQUwiKQ0KUEkgPC0gZmlsdGVyKFBJLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClBJIDwtIHNlbGVjdChQSSwgLVBlcmlvZG8pDQpQSSA8LSBzZWxlY3QoUEksIC1gVGlwbyBkZSBQYXNhamVyb2ApDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERixQSSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGwgPSBUUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiTlBJIiA9ICJOcm8gUGFzYWplcm9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiROUElbaXMubmEoREYkTlBJKV0gPC0gMA0KDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBOdW1lcm8gZGUgUGFzYWplcm9zIE5hY2lvbmFsZXMgKE5QTikNCg0KYGBge3J9DQpQTiA8LSBmaWx0ZXIoVFAsIGBUaXBvIGRlIFBhc2FqZXJvYCA9PSAiTkFDSU9OQUwiKQ0KUE4gPC0gZmlsdGVyKFBOLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClBOIDwtIHNlbGVjdChQTiwgLVBlcmlvZG8pDQpQTiA8LSBzZWxlY3QoUE4sIC1gVGlwbyBkZSBQYXNhamVyb2ApDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERixQTiwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIk5QTiIgPSAiTnJvIFBhc2FqZXJvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkTlBOW2lzLm5hKERGJE5QTildIDwtIDANCg0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNCiMjIFVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBUIFUgVSBBIE5BQ0lPTkFMIChUVVVBTikNCg0KYGBge3J9DQpUVVVBTiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIlQgVSBVIEEgTkFDSU9OQUwiKQ0KVFVVQU4gPC0gZmlsdGVyKFRVVUFOLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClRVVUFOIDwtIHNlbGVjdChUVVVBTiwgLSdUaXBvIEluZ3Jlc28nKQ0KVFVVQU4gPC0gc2VsZWN0KFRVVUFOLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KVFVVQU4gPC0gc2VsZWN0KFRVVUFOLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzDQpERiA8LSBtZXJnZShERiwgVFVVQU4sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJUVVVBTl9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgVFVVQU4sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJUVVVBTiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRUVVVBTl9WRVJbaXMubmEoREYkVFVVQU5fVkVSKV0gPC0gMA0KREYkVFVVQU5fVkVSW0RGJFRVVUFOX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRUVVVBTl9WRVJbREYkVFVVQU5fVkVSID09ICIwIl0gPC0gIk5vIg0KREYkVFVVQU5baXMubmEoREYkVFVVQU4pXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIFQgVSBVIEEgSU5URVJOQUNJT05BTCAoVFVVQUkpDQoNCmBgYHtyfQ0KVFVVQUkgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJUIFUgVSBBIElOVEVSTkFDSU9OQUwiKQ0KVFVVQUkgPC0gZmlsdGVyKFRVVUFJLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClRVVUFJIDwtIHNlbGVjdChUVVVBSSwgLSdUaXBvIEluZ3Jlc28nKQ0KVFVVQUkgPC0gc2VsZWN0KFRVVUFJLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KVFVVQUkgPC0gc2VsZWN0KFRVVUFJLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIFRVVUFJLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQUlfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKSNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIFRVVUFJLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQUkiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KDQpERiRUVVVBSV9WRVJbaXMubmEoREYkVFVVQUlfVkVSKV0gPC0gMA0KREYkVFVVQUlfVkVSW0RGJFRVVUFJX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRUVVVBSV9WRVJbREYkVFVVQUlfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkVFVVQUlbaXMubmEoREYkVFVVQUkpXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFURVJSSVpBSkUgWSBERVNQRUdVRSAoSVJBRCkNCg0KYGBge3J9DQpJUkFEIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQVRFUlJJWkFKRSBZIERFU1BFR1VFIikNCklSQUQgPC0gZmlsdGVyKElSQUQsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJBRCA8LSBzZWxlY3QoSVJBRCwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJBRCA8LSBzZWxlY3QoSVJBRCwgLSdSdWJybyBJbmdyZXNvJykNCklSQUQgPC0gc2VsZWN0KElSQUQsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUkFELCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJBRF9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUkFELCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJBRCIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJElSQURfVkVSW2lzLm5hKERGJElSQURfVkVSKV0gPC0gMA0KREYkSVJBRF9WRVJbREYkSVJBRF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkSVJBRF9WRVJbREYkSVJBRF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRJUkFEW2lzLm5hKERGJElSQUQpXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFMUVVJTEVSIEFSRUFTIERFIE1BTlRFTklNSUVOVE8gKEFBRE0pDQoNCmBgYHtyfQ0KQUFETSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIEFSRUFTIERFIE1BTlRFTklNSUVOVE8iKQ0KQUFETSA8LSBmaWx0ZXIoQUFETSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBQURNIDwtIHNlbGVjdChBQURNLCAtJ1RpcG8gSW5ncmVzbycpDQpBQURNIDwtIHNlbGVjdChBQURNLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQUFETSA8LSBzZWxlY3QoQUFETSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFBRE0sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBQURNX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFBRE0sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBQURNIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCg0KREYkQUFETV9WRVJbaXMubmEoREYkQUFETV9WRVIpXSA8LSAwDQpERiRBQURNX1ZFUltERiRBQURNX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBQURNX1ZFUltERiRBQURNX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFBRE1baXMubmEoREYkQUFETSldIDwtIDANCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gQUxRVUlMRVIgREUgRVNQQUNJT1MgUFVCTElDSVRTQVJJT1MgKEFERVApDQoNCmBgYHtyfQ0KQURFUCA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIERFIEVTUEFDSU9TIFBVQkxJQ0lUU0FSSU9TIikNCkFERVAgPC0gZmlsdGVyKEFERVAsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQURFUCA8LSBzZWxlY3QoQURFUCwgLSdUaXBvIEluZ3Jlc28nKQ0KQURFUCA8LSBzZWxlY3QoQURFUCwgLSdSdWJybyBJbmdyZXNvJykNCkFERVAgPC0gc2VsZWN0KEFERVAsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBREVQLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQURFUF9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBREVQLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQURFUCIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJEFERVBfVkVSW2lzLm5hKERGJEFERVBfVkVSKV0gPC0gMA0KREYkQURFUF9WRVJbREYkQURFUF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQURFUF9WRVJbREYkQURFUF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBREVQW2lzLm5hKERGJEFERVApXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIEFMUVVJTEVSIExPQ0FMRVMgQ09NRVJDSUFMRVMgKEFMQykNCg0KYGBge3J9DQpBTEMgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJBTFFVSUxFUiBMT0NBTEVTIENPTUVSQ0lBTEVTIikNCkFMQyA8LSBmaWx0ZXIoQUxDLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCkFMQyA8LSBzZWxlY3QoQUxDLCAtJ1RpcG8gSW5ncmVzbycpDQpBTEMgPC0gc2VsZWN0KEFMQywgLSdSdWJybyBJbmdyZXNvJykNCkFMQyA8LSBzZWxlY3QoQUxDLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgQUxDLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUxDX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBTEMsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBTEMiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KDQpERiRBTENfVkVSW2lzLm5hKERGJEFMQ19WRVIpXSA8LSAwDQpERiRBTENfVkVSW0RGJEFMQ19WRVIgIT0gMF0gPC0gIlNpIg0KREYkQUxDX1ZFUltERiRBTENfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkQUxDW2lzLm5hKERGJEFMQyldIDwtIDANCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gQUxRVUlMRVIgT0ZJQ0lOQVMgT1BFUkFDSU9ORVMgQUVST0zDjU5FQVMgKEFPT0EpDQoNCmBgYHtyfQ0KQU9PQSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIE9GSUNJTkFTIE9QRVJBQ0lPTkVTIEFFUk9Mw41ORUFTIikNCkFPT0EgPC0gZmlsdGVyKEFPT0EsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQU9PQSA8LSBzZWxlY3QoQU9PQSwgLSdUaXBvIEluZ3Jlc28nKQ0KQU9PQSA8LSBzZWxlY3QoQU9PQSwgLSdSdWJybyBJbmdyZXNvJykNCkFPT0EgPC0gc2VsZWN0KEFPT0EsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBT09BLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQU9PQV9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgQU9PQSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFPT0EiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkQU9PQV9WRVJbaXMubmEoREYkQU9PQV9WRVIpXSA8LSAwDQpERiRBT09BX1ZFUltERiRBT09BX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBT09BX1ZFUltERiRBT09BX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFPT0FbaXMubmEoREYkQU9PQSldIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gQUxRVUlMRVJFUyBERSBBTE1BQ0VOL0hBTkdBUiAoQURBSCkNCg0KYGBge3J9DQpBREFIIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQUxRVUlMRVJFUyBERSBBTE1BQ0VOL0hBTkdBUiIpDQpBREFIIDwtIGZpbHRlcihBREFILEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCkFEQUggPC0gc2VsZWN0KEFEQUgsIC0nVGlwbyBJbmdyZXNvJykNCkFEQUggPC0gc2VsZWN0KEFEQUgsIC0nUnVicm8gSW5ncmVzbycpDQpBREFIIDwtIHNlbGVjdChBREFILCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgQURBSCwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFEQUhfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzIA0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFEQUgsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBREFIIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCkRGJEFEQUhfVkVSW2lzLm5hKERGJEFEQUhfVkVSKV0gPC0gMA0KREYkQURBSF9WRVJbREYkQURBSF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQURBSF9WRVJbREYkQURBSF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBREFIW2lzLm5hKERGJEFEQUgpXSA8LSAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFURU5DScOTTiBFTiBIT1JBUyBFWFRSQVMgKEFFSEUpDQoNCmBgYHtyfQ0KQUVIRSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFURU5DScOTTiBFTiBIT1JBUyBFWFRSQVMiKQ0KQUVIRSA8LSBmaWx0ZXIoQUVIRSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBRUhFIDwtIHNlbGVjdChBRUhFLCAtJ1RpcG8gSW5ncmVzbycpDQpBRUhFIDwtIHNlbGVjdChBRUhFLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQUVIRSA8LSBzZWxlY3QoQUVIRSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFFSEUsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBRUhFX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBRUhFLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUVIRSIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRBRUhFX1ZFUltpcy5uYShERiRBRUhFX1ZFUildIDwtIDANCkRGJEFFSEVfVkVSW0RGJEFFSEVfVkVSICE9IDBdIDwtICJTaSINCkRGJEFFSEVfVkVSW0RGJEFFSEVfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkQUVIRVtpcy5uYShERiRBRUhFKV0gPC0gMA0KYGBgDQoNCiMjIFVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBFU1RBQ0lPTkFNSUVOVE8gQUVST05BVkVTIChJUkVBKQ0KDQpgYGB7cn0NCklSRUEgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJFU1RBQ0lPTkFNSUVOVE8gQUVST05BVkVTIikNCklSRUEgPC0gZmlsdGVyKElSRUEsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJFQSA8LSBzZWxlY3QoSVJFQSwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJFQSA8LSBzZWxlY3QoSVJFQSwgLSdSdWJybyBJbmdyZXNvJykNCklSRUEgPC0gc2VsZWN0KElSRUEsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUkVBLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJFQV9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgSVJFQSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSRUEiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJFQV9WRVJbaXMubmEoREYkSVJFQV9WRVIpXSA8LSAwDQpERiRJUkVBX1ZFUltERiRJUkVBX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRJUkVBX1ZFUltERiRJUkVBX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSRUFbaXMubmEoREYkSVJFQSldIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gSU5HUkVTT1MgRklOQU5DSUVST1MgKElSSUYpDQoNCmBgYHtyfQ0KSVJJRiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIklOR1JFU09TIEZJTkFOQ0lFUk9TIikNCklSSUYgPC0gZmlsdGVyKElSSUYsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJJRiA8LSBzZWxlY3QoSVJJRiwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJJRiA8LSBzZWxlY3QoSVJJRiwgLSdSdWJybyBJbmdyZXNvJykNCklSSUYgPC0gc2VsZWN0KElSSUYsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUklGLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJJRl9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgSVJJRiwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSSUYiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJJRl9WRVJbaXMubmEoREYkSVJJRl9WRVIpXSA8LSAwDQpERiRJUklGX1ZFUltERiRJUklGX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRJUklGX1ZFUltERiRJUklGX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSSUZbaXMubmEoREYkSVJJRildIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gUkVFTUJPTFNPUyAoSVJSKQ0KDQpgYGB7cn0NCklSUiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIlJFRU1CT0xTT1MiKQ0KSVJSIDwtIGZpbHRlcihJUlIsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJSIDwtIHNlbGVjdChJUlIsIC0nVGlwbyBJbmdyZXNvJykNCklSUiA8LSBzZWxlY3QoSVJSLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KSVJSIDwtIHNlbGVjdChJUlIsIC0nUGVyaW9kbycpDQoNCklSUiA8LSBmaWx0ZXIoSVJSLCBgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCAhPSAwKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgSVJSLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJSX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUlIsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJJUlIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJSX1ZFUltpcy5uYShERiRJUlJfVkVSKV0gPC0gMA0KREYkSVJSX1ZFUltERiRJUlJfVkVSICE9IDBdIDwtICJTaSINCkRGJElSUl9WRVJbREYkSVJSX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSUltpcy5uYShERiRJUlIpXSA8LSAwDQpgYGANCg0KIyMgQWdyZWdhbmRvIGxhIHZhcmlhYmxlIE51bWVybyBkZSBQYXNhamVyb3MgVG90YWxlcyAoTlApDQoNCmBgYHtyfQ0KREYgJT4lIG11dGF0ZShOUCA9IE5QTiArIE5QSSkgLT4gREYNCiNOdW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMNCmBgYA0KDQojIyBFbGltaW5hY2nDs24gZGUgZGF0b3MgeSBhcnJlZ2xvcw0KDQpgYGB7cn0NCiMgU2kgZXMgcXVlIG5vIHRlbmVtb3MgZWwgbm9tYnJlIGRlbCBhZXJvcHVlcnRvIG8gc3UgaW5mcmFlc3RydWN0dXJhIChTaWVtcHJlIGRlYmUgdmVuaXIgYWNvbXBhw7FhZGEgZGVsIG5vbWJyZSksIGxhIHVuaWRhZCBtdWVzdHJhbCBubyBwb2Ryw6EgZW50cmFyIGFsIGFuw6FsaXNpcyBwdWVzIHBvciBlamVtcGxvIHNpIG5vcyBkaWNlbiBjdWFudG8gZ2FubyB1biBhZXJvcHVlcnRvIGRlc2Nvbm9jaWRvLCBlc3RvIG5vIG5vcyBkaXLDoSBuYWRhLg0KDQoNCkRGJE1lcyA9IGZhY3RvcihERiRNZXMsIGxldmVscyA9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2V0aWVtYnJlIiwiT2N0dWJyZSIsIk5vdmllbWJyZSIsIkRpY2llbWJyZSIpKQ0KREYgPC0gYXJyYW5nZShERiwgQcOxbywgTWVzKQ0KDQpERiRBZXJvcHVlcnRvW0RGJEFlcm9wdWVydG8gPT0gJ05vIHByZWNpc2EnXSA8LSBOQQ0KREYkQWVyb3B1ZXJ0b1tERiRBZXJvcHVlcnRvID09ICctJ10gPC0gTkENCkRGJEluZnJhZXN0cnVjdHVyYVtERiRJbmZyYWVzdHJ1Y3R1cmEgPT0gJy0nXSA8LSBOQQ0KDQpERiA8LSBmaWx0ZXIoREYsIEluZnJhZXN0cnVjdHVyYSAhPSBpcy5uYSgiSW5mcmFlc3RydWN0dXJhIikgJiBBZXJvcHVlcnRvICE9IGlzLm5hKCJBZXJvcHVlcnRvIikpDQoNCkRGICU+JSBtdXRhdGUoIkVudGlkYWRfSW5mcmFlc3RydWN0dXJhIiA9DQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQURQIiwgIkFlcm9wdWVydG9zIGRlbCBQZXLDuiBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJBQVAiLCAiQWVyb3B1ZXJ0b3MgQW5kaW5vcyBkZWwgUGVyw7ogUy5BLiIsDQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQ09SIiwgIkNPUlBBQyBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJMQVAiLCAiTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MLiIsSW5mcmFlc3RydWN0dXJhKSkpKSkgLT4gREYNCmBgYA0KDQpgYGB7cn0NCnN1bShjb21wbGV0ZS5jYXNlcyhERikpDQpgYGANCg0KYGBge3J9DQoNCkRGJE1lcyA9IGZhY3RvcihERiRNZXMsIGxldmVscyA9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2V0aWVtYnJlIiwiT2N0dWJyZSIsIk5vdmllbWJyZSIsIkRpY2llbWJyZSIpKQ0KREYgPC0gYXJyYW5nZShERiwgQcOxbywgTWVzKQ0KYGBgDQoNCiMjIEV4cG9ydGFuZG8gbGEgYmFzZSBkZSBkYXRvcw0KDQpgYGB7cn0NCndyaXRlX2NzdihERiwiQmFzZUxpbXBpYXYyLmNzdiIpDQoNCmBgYA0KDQojIEltcG9ydGFuZG8gbGEgYmFzZSBkYXRvcyBsaW1waWENCg0KYGBge3J9DQoNCnJtKGxpc3QgPSBscygpKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RyaXgpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHN0cmluZ2kpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoTUFTUykNCg0KREYgPC0gcmVhZF9jc3YoIkJhc2VMaW1waWF2Mi5jc3YiKQ0KDQpgYGANCg0KIyBWYXJpYWJsZXMNCg0KKipBw7FvOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2EgZWwgYcOxbyBkZSBsYSByZWNvbGVjY2nDs24gZGUgaW5mb3JtYWNpw7NuLg0KDQoqKk1lczoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgaW5kaWNhIGVsIG1lcyBkZSBsYSByZWNvbGVjY2nDs24gZGUgaW5mb3JtYWNpw7NuLg0KDQoqKkFlcm9wdWVydG86KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBlbCBhZXJvcHVlcnRvIGRlbCBjdWFsIHNlIHJlY29sZWN0YSBsYSBpbmZvcm1hY2nDs24NCg0KKipJbmZyYWVzdHJ1Y3R1cmE6KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBlbiBhY3LDs25pbW8gYSBxdWUgZW50aWRhZCBwZXJ0ZW5lY2UgbGEgaW5mcmFlc3RydWN0dXJhIGRlbCBhZXJvcHVlcnRvIGRlbCBjdWFsIHNlIHJlY29sZWN0YSBsYSBpbmZvcm1hY2nDs24uDQoNCioqRW50aWRhZF9JbmZyYWVzdHJ1Y3R1cmE6KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBhIHF1ZSBlbnRpZGFkIHBlcnRlbmVjZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbi4NCg0KKipJVDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqSVI6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGxvcyBpbmdyZXNvcyByZWd1bGFkb3MgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqVFVVQU4qKjogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBxdWUgaGEgZ2VuZXJhZG8gbGEgKlRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPIGRlIHRpcG8gbmFjaW9uYWwuKg0KDQoqKlRVVUFOKio6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcXVlIGhhIGdlbmVyYWRvIGxhICpUQVJJRkEgVU5JRklDQURBIFBPUiBVU08gREUgQUVST1BVRVJUTyBkZSB0aXBvIGludGVybmFjaW9uYWwuKg0KDQoqKk5QSToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQoqKk5QTjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBuYWNpb25hbGVzIHF1ZSBoYSByZWdpc3RyYWRvIGVsIGFlcm9wdWVydG8NCg0KKipJUkFEX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipJUkFEOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgZGVsIGFlcm9wdWVydG8gcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipBQURNX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIMOhcmVhcyBkZSBtYW50ZW5pbWllbnRvLg0KDQoqKkFBRE06KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgw6FyZWFzIGRlIG1hbnRlbmltaWVudG8uDQoNCioqQURFUF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBlc3BhY2lvcyBkZSBwdWJsaWNpZGFkLg0KDQoqKkFERVA6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgZXNwYWNpb3MgZGUgcHVibGljaWRhZC4NCg0KKipBTENfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBTEM6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBT09BX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIG9maWNpbmFzIGRlIG9wZXJhY2lvbmVzIGRlIGFlcm9sw61uZWFzLg0KDQoqKkFPT0E6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgb2ZpY2luYXMgZGUgb3BlcmFjaW9uZXMgZGUgYWVyb2zDrW5lYXMuDQoNCioqQURBSF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQURBSDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQUVIRV9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBsYSBhdGVuY2nDs24gZW4gaG9yYXMgZXh0cmFzLg0KDQoqKkFFSEU6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgbGEgYXRlbmNpw7NuIGVuIGhvcmFzIGV4dHJhcy4NCg0KKipJUkVBX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGVzdGFjaW9uYW1pZW50byBkZSBhZXJvbmF2ZXMuDQoNCioqSVJFQToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBlc3RhY2lvbmFtaWVudG8gZGUgYWVyb25hdmVzLg0KDQoqKklSSUZfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSSUY6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSUl9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciByZWVtYm9sc29zLg0KDQoqKklSUjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciByZWVtYm9sc29zLg0KDQoqKk5QOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0by4NCg0KIyBEZXNjcmlwdG9yZXMgTnVtw6lyaWNvcw0KDQpgYGB7cn0NCmN2IDwtIGZ1bmN0aW9uKHgpew0KICAgIHJldHVybihzZCh4LCBuYS5ybT1UKS9tZWFuKHgsIG5hLnJtPVQpKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KdGFibGEgPC0gZGF0YS5mcmFtZShWYXJpYWJsZXMgPSBjKCdJVCcsICdOUE4nLCAnTlBJJywgJ1RVVUFOJywnVFVVQUknKSwNCiAgICAgICAgICAgICAgICAgICAgTWVkaWEgPSBjKG1lYW4oREYkSVQsIG5hLnJtPVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFOLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFJLCBuYS5ybT0gVCkpLA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgTWVkaWFuYSA9IGMobWVkaWFuKERGJElULCBuYS5ybT1UKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBTiwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBSSwgbmEucm09IFQpKSwgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBEZXN2aWFjaW9uID0gYyhzZChERiRJVCwgbmEucm09VCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUEksIG5hLnJtPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QoREYkVFVVQUksIG5hLnJtPSBUKSksIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgVmFyaWFuemEgPSBjKHZhcihERiRJVCwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiROUEksIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBSYW5nb0ludGVyY3VhcnRpbCA9IGMoSVFSKERGJElULCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBJLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkVFVVQU4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElRUihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBDb2VmaWNpZW50ZVZhcmlhY2lvbiA9IGMoY3YoREYkSVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSkpDQp0YWJsYQ0KYGBgDQoNCkRlIGxhIHRhYmxhIHBvZGVtb3MgY29uc2VndWlyIGxhIHNpZ3VpZW50ZSBpbmZvcm1hY2nDs246DQoNCi0gICBMYSBlc2NhbGEgY29uIGxhIHF1ZSBzZSB0cmFiYWphIGVzIGJhc3RhbnRlIGdyYW5kZSwgZGUgYWjDrSBlbCBoZWNobyBxdWUgbGEgdmFyaWFuemEgeSBkZXN2aWFjacOzbiBzZWFuIHRhbiBncmFuZGUuDQoNCi0gICBUYW50byBsYSB2YXJpYW56YSBjb21vIGxhIGRlc3ZpYWNpw7NuIG5vcyBpbmRpY2FuIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIEluZ3Jlc29zIFRvdGFsZXMsIGVsIE51bWVybyBkZSBQYXNhamVyb3MgTmFjaW9uYWxlcyB5IGVsIE51bWVybyBkZSBQYXNhamVyb3MgSW50ZXJuYWNpb25hbGVzIGVzdMOhbiBtdXkgZGlzcGVyc29zLg0KDQotICAgU2UgYXByZWNpYSB1biBmZW7Ds21lbm8gcXVlIGxhIG1lZGlhbmEgeSBlbCByYW5nbyBpbnRlcmN1YXJ0aWwgZGUgbGEgdmFyaWFibGUgUGFzYWplcm9zIGludGVybmFjaW9uYWxlcyBlcyAwLiBFc3RvIHF1aWVyZSBkZWNpciBxdWUgaGF5IG11Y2hvcyBhZXJvcHVlcnRvcyBsb3MgY3VhbGVzIG5vIHN1ZWxlbiByZWNpYmlyIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMuDQoNCiMgRGVzY3JpcHRvcmVzIEdyw6FmaWNvcw0KDQojIyBOdW1lcm8gZGUgUGFzYWplcm9zIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQoNCmBgYA0KDQpDb21lbnphbW9zIGNvbXBhcmFuZG8gZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB0b3RhbGVzLCBzdW1hIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgeSBuYWNpb25hbGVzLCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGUgY2FkYSBhZXJvcHVlcnRvIGVuIGRldGVybWluYWRvIG1lcyB5IGHDsW8gZW4gbWlsbG9uZXMgZGUgZG9sYXJlcy4gQSBzaW1wbGUgdmlzdGEgc2UgcHVlZGUgdmVyIHVuIGNpZXJ0byB0aXBvIGRlIHJlbGFjacOzbiBsaW5lYWwsIHNpbiBlbWJhcmdvIHRlbmVtb3MgcXVlIGNvbXByb2JhcmxvLiBVc2FyZW1vcyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24geWEgcXVlIGVzdGUgbm8gdG9tYSBlbiBjdWVudGEgbGEgZXNjYWxhIGRlIGxhcyB1bmlkYWRlcywgcGVyZmVjdG8gcGFyYSBudWVzdHJvIGVzdHVkaW8uDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiROUCwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkNvbiBsYSBpbmZvcm1hY2nDs24gc3VtaW5pc3RyYWRhIGRlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gc2UgZGVkdWNlIHF1ZSBsYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGVsIG51bWVybyBkZSBwYXNhamVyb3MgeSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlcyBidWVuYSwgY2FzaSBwZXJmZWN0YSB5IGFzY2VuZGVudGUuIEVzIGRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGF1bWVudGFyYW4gZW4gY3VhbnRvIGF1bWVudGUgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcy4NCg0KQWhvcmEgY3JlYXJlbW9zIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3J9DQoNCm1vZGVsbyA9IGxtKERGJElUIH4gREYkTlAsIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUC8xMDAwLCAiWSI9REYkSVQvMTAwMDAwMCkNCm1vZGVsbyA9IGxtKGQkWSB+IGQkWCwgZGF0YT1kKQ0KbW9kZWxvDQpgYGANCg0KSGVtb3MgY3JlYWRvIGRvcyBtb2RlbG9zIHF1ZSBlbiByZWFsaWRhZCBzb24gZWwgbWlzbW8gcGVybyBhIGRpZmVyZW50ZXMgZXNjYWxhcy4gRWwgcHJpbWVybyBub3Mgc2lydmUgcGFyYSB1c2FyIGRpcmVjdGFtZW50ZSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHkgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcy4gRWwgc2VndW5kbyBwYXJhIHVzYXIgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB5IGNvbnNlZ3VpciBsb3MgaW5ncmVzb3MgdG90YWxlcyBlbiBtaWxsb25lcyBkZSBkb2xhcmVzLiBBbWJvcyBtb2RlbG9zIG5vcyBwZXJtaXRlbiBhcHJveGltYXIsIHByZWRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIHVuIGFlcm9wdWVydG8gZW4gZGV0ZXJtaW5hZG8gbWVzIHkgYcOxbyB1c2FuZG8gbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGxsZXZvIGVuIGVsIG1pc21vIGxhcHNvIGRlIHRpZW1wby4NCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQphYmxpbmUoYT0gLTAuMTQ4OTAsIGI9MC4wMTY0NiwgY29sPSJncmVlbiIpDQpgYGANCg0KIyMgTnVtZXJvIGRlIFBhc2FqZXJvcyBOYWNpb25hbGVzIGUgSW50ZXJuYWNpb25hbGVzIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KDQpwbG90KERGJE5QTi8xMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIk51bWVybyBkZSBwYXNhamVyb3MgbmFjaW9uYWxlcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJyZWQiLCBwY2g9IuKAoiIpDQoNCnBsb3QoREYkTlBJLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iYmx1ZSIsIHBjaD0i4oCiIikNCmBgYA0KDQpBaG9yYSB2YW1vcyBhIGFuYWxpemFyIGxhIHJlbGFjacOzbiBkZSBsb3MgdGlwb3MgZGUgcGFzYWplcm9zIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcy4gRGUgbnVldm8gdXNhcmVtb3MgZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHRhbnRvIHBhcmEgbG9zIHBhc2FqZXJvcyBuYWNpb25hbGVzIGNvbW8gaW50ZXJuYWNpb25hbGVzLg0KDQpgYGB7cn0NCmNvcihERiRJVCwgREYkTlBOLCB1c2U9ImNvbXBsZXRlLm9icyIpDQpjb3IoREYkSVQsIERGJE5QSSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkRlIGxvcyBjb2VmaWNpZW50ZXMgZGFkb3Mgc2UgZW5jdWVudHJhIHF1ZToNCg0KLSAgIEFtYm9zIGRlbXVlc3RyYW4gcXVlIHRhbnRvIGxvcyBwYXNhamVyb3MgbmFjaW9uYWxlcyBjb21vIGludGVybmFjaW9uYWxlcyBwb3NlZW4gdW5hIGJ1ZW5hIHkgYXNjZW5kZW50ZSByZWxhY2nDs24gbGluZWFsIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcy4NCi0gICBBbWJvcyBzb24gbWVub3JlcyBhbCAqKmNvcioqIGRlIGxvcyBwYXNhamVyb3MgdG90YWxlcyBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMuIEluZGljYSBxdWUgc2kgc2UgdXNhIHNvbG8gYSBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMgbyBzb2xvIGEgbG9zIGludGVybmFjaW9uYWxlcyBwYXJhIGFwcm94aW1hciBsb3MgaW5ncmVzb3MgdG90YWxlcywgc2UgdGVuZHLDoSB1bmEgcHJlY2lzacOzbiBtZW5vciBhIHF1ZSBzaSBzZSB1c2Fyw6EgbGEgc3VtYSBkZSBhbWJvcy4NCi0gICBFbCAqKmNvcioqIGRlIGxvcyBwYXNhamVyb3MgaW50ZXJuYWNpb25hbGVzIGVzIGxpZ2VyYW1lbnRlIHN1cGVyaW9yIGFsIGRlIGxvcyBwYXNhamVyb3MgbmFjaW9uYWxlcywgbW9zdHJhbmRvIHF1ZSBzdSByZWxhY2nDs24gbGluZWFsIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcyBlcyBsaWdlcmFtZW50ZSBtw6FzIGFjb3JkZSBxdWUgbGEgcmVsYWNpw7NuIGxpbmVhbCBkZSBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMuDQoNCkFob3JhIGNvbnN0cnV5YW1vcyBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCBwYXJhIGNhZGEgdW5vLg0KDQpgYGB7cn0NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiROUE4sIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUE4vMTAwMCwgIlkiPURGJElULzEwMDAwMDApDQptb2RlbG8gPSBsbShkJFkgfiBkJFgsIGRhdGE9ZCkNCm1vZGVsbw0KDQptb2RlbG8gPSBsbShERiRJVCB+IERGJE5QSSwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJE5QSS8xMDAwLCAiWSI9REYkSVQvMTAwMDAwMCkNCm1vZGVsbyA9IGxtKGQkWSB+IGQkWCwgZGF0YT1kKQ0KbW9kZWxvDQoNCnJtKGQpDQpgYGANCg0KVmVtb3MgcXVlIGxvcyBtb2RlbG9zIGRpZmllcmVuIGVuIHVuYSBjYW50aWRhZCBjb25zaWRlcmFibGUgZW4gY3VhbnRvIGEgc3UgcGVuZGllbnRlLCBzaW4gZW1iYXJnbywgc3UgaW50ZXJjZXB0byBlcyBiYXN0YW50ZSBzaW1pbGFyLCB2YW1vcyBhIGdyYWZpY2FyIGVzdG9zIG1vZGVsb3MuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCg0KcGxvdChERiROUE4vMTAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJOdW1lcm8gZGUgcGFzYWplcm9zIG5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0icmVkIiwgcGNoPSLigKIiKQ0KYWJsaW5lKGE9IC0wLjM2MDMzLCBiPTAuMDI0NTEsIGNvbD0iI2Y3MjU4NSIpDQoNCnBsb3QoREYkTlBJLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iYmx1ZSIsIHBjaD0i4oCiIikNCmFibGluZShhPSAwLjMxOTk2LCBiPTAuMDQ3NzIsIGNvbD0iIzAwNzdiNiIpDQpgYGANCg0KIyMgQW5hbGl6YW5kbyBsYSBkaXN0cmlidWNpw7NuIGRlIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwbG90X2x5KHggPSB+REYkSVQvMTAwMDAwMCwNCiAgICAgICAgdHlwZT0iaGlzdG9ncmFtIiwNCiAgICAgICAgY29sb3IgPSB+REYkSW5mcmFlc3RydWN0dXJhLA0KICAgICAgICBuYmluc3ggPSAxMDANCiAgICAgICAgKSU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiRnJlY3VlbmNpYSIgKSwNCiAgICB4YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgKE1pbGxvbmVzIGRlIFVTJCkiLA0KICAgICAgICAgICAgICAgICAgbnRpY2tzID0gMjApKQ0KYGBgDQoNCkdyYWNpYXMgYWwgaGlzdG9ncmFtYSBzZSBkaWNlIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgc29uIHRvdGFsbWVudGUgYXNpbcOpdHJpY29zIHkgc2UgZW5jdWVudHJhbiBhY3VtdWxhZG9zIGVuIHVuIGludGVydmFsbyBkZSAwIC0gMC41IG1pbGxvbmVzIGRlIGRvbGFyZXMuIEVzIGRlY2lyIGxhIG1heW9yw61hIGRlIGFlcm9wdWVydG9zIGRldGVybWluYWRvcyBlbiBjaWVydG8gbWVzIHkgY2llcnRvIGHDsW8gcG9zZWUgdW5vcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGVudHJlIDAgeSAwLjUgbWlsbG9uZXMgZGUgZG9sYXJlcy4gRXN0byBwdWVkZSBvY3VycmlyIGRlYmlkbyBhIGRhdG9zIGF0w61waWNvcywgY29uc3RydXlhbW9zIHVuIEJveHBsb3QgcGFyYSBxdWUgbm9zIGF5dWRlLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHg9fkRGJElULzEwMDAwMDAsDQogICAgICAgICAgICB0eXBlID0gImJveCIpJT4lDQpsYXlvdXQoDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KVXNhbmRvIHVuIEJveHBsb3Qgc2ltcGxlIHNlIGNvbXBydWViYSBjb21vIGxvcyBkYXRvcyBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlc3TDoW4gZGVtYXNpZG9zIGRpc3BlcnNvcyBncmFjaWFzIGEgY2llcnRhIGNhbnRpZGFkIGRlIGRhdG9zIGF0aXBpY29zLiBBaG9yYSBlcyBuZWNlc2FyaW8gYXZlcmlndWFyIGRlIGRvbmRlIHByb3ZpZW5lbiBlc3RvcyBkYXRvcyBhdMOtcGljb3MgeSBxdWUgbm9zIHF1aWVyZW4gZGVjaXIuIFBhcmEgZWxsbyBjcmVhcmVtb3MgZGlmZXJlbnRlcyBCb3hwbG90cyBiYXNhZG9zIGVuIG1lc2VzLCBpbmZyYWVzdHJ1Y3R1cmFzIHkgYWVyb3B1ZXJ0b3MuDQoNCmBgYHtyfQ0KcGxvdF9seShERiwgeCA9IH5JVC8xMDAwMDAwLCANCiAgICAgICAgeSA9IH5NZXMsIA0KICAgICAgICBjb2xvcj0gfk1lcywgDQogICAgICAgIHR5cGU9ImJveCIpICU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiTWVzIiksDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KQ29uIGVzdGUgZ3LDoWZpY28gcG9kZW1vcyBkZXNjYXJ0YXIgcXVlIGxvcyBkYXRvcyBhdMOtcGljb3MgcHJvdmVuZ2FuIGRlIHVuIG8gdmFyaW9zIG1lc2VzIGVuIGVzcGVjw61maWNvLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHggPSB+SVQvMTAwMDAwMCwgDQogICAgICAgIHkgPSB+SW5mcmFlc3RydWN0dXJhLCANCiAgICAgICAgY29sb3I9IH5FbnRpZGFkX0luZnJhZXN0cnVjdHVyYSwgDQogICAgICAgIHR5cGU9ImJveCIpICU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiSW5mcmFlc3RydWN0dXJhIiksDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KRW4gZXN0ZSBncsOhZmljbyBzZSBvYnNlcnZhIGNvbW8gTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MIHJlYmFzYSBwb3IgbXVjaG8gYSBsYXMgb3RyYXMgaW5mcmFlc3RydWN0dXJhcyBlbiBjdWFudG8gYSBpbmdyZXNvcyB0b3RhbGVzIHNlIHJlZmllcmUuIEFxdcOtIHBvZGVtb3MgeWEgc2FiZXIgcXVlIGVzb3MgZGF0b3MgYXTDrXBpY29zIGRlIGluZ3Jlc29zIGVzdMOhbiBnZW5lcmFkb3MgZW4gc3UgZ3JhbiBtYXlvcsOtYSBwb3IgbGEgaW5mcmFlc3RydWN0dXJhIExpbWEgQWlycG9ydCBQYXJ0bmVycyBTLlIuTC4gQWRlbcOhcyBlcyBpbXBvcnRhbnRlIG1lbmNpb25hciBxdWUgbGEgaW5mcmFlc3RydWN0dXJhIENPUiBubyBhcGFyZWNlIGVuIGxhIGdyw6FmaWNhIHB1ZXMgbm8gaGEgZGVjbGFyYWRvIG5pbmfDum4gaW5ncmVzbyB0b3RhbC4NCg0KYGBge3J9DQpwbG90X2x5KERGLCB4ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB5ID0gfkFlcm9wdWVydG8sIA0KICAgICAgICBjb2xvcj0gfkFlcm9wdWVydG8sIA0KICAgICAgICB0eXBlPSJib3giDQogICAgICAgICkgJT4lDQpsYXlvdXQoeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJBZXJvcHVlcnRvcyIpLA0KICAgIHhheGlzID0gbGlzdCggdGl0bGUgPSAiSW5ncmVzb3MgdG90YWxlcyAoTWlsbG9uZXMgZGUgVVMkKSIpKQ0KYGBgDQoNCkdyYWNpYXMgYSBsb3MgMyBncsOhZmljb3MgcG9kZW1vcyBjb25jbHVpciBxdWU6DQoNCi0gICBFbCBhZXJvcHVlcnRvIGRlIExpbWEgY3V5YSBlbnRpZGFkIHByZXN0YWRvcmEgZXMgbGEgTEFQLCBlcyBsYSByZXNwb25zYWJsZSBkZSBsb3MgZGF0b3MgYXTDrXBpY29zIHkgYWRlbcOhcyBlcyBlbCBxdWUgbcOhcyBpbmdyZXNvcyB0b3RhbGVzIGdlbmVyYS4NCi0gICBMYSBpbmZyYWVzdHJ1Y3R1cmEgTEFQIHRyYWJhamEgZW4gTGltYSB5IHNlIHJlZmllcmUgYWwgQWVyb3B1ZXJ0byBJbnRlcm5hY2lvbmFsIEpvcmdlIENow6F2ZXouIEVzdG8gbm9zIHF1aWVyZSBkZWNpciBxdWUgZW4gZWwgUGVyw7osIGVsIGFlcm9wdWVydG8gcXVlIGdlbmVyYSBtw6FzIGluZ3Jlc29zIGVzIGVsIEpvcmdlIENow6F2ZXouDQoNCiMjIE51bWVybyBkZSBQYXNhamVyb3MgdnMgQWVyb3B1ZXJ0b3MNCg0KYGBge3J9DQpwbG90X2x5KERGLHkgPSB+TlAvMTAwMCwNCiAgICAgICAgeCA9IH5hcy5mYWN0b3IoQWVyb3B1ZXJ0byksIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yPWMoImxpZ2h0Ymx1ZSIpKQ0KICAgICAgICApJT4lDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiQWVyb3B1ZXJ0b3MiKSwNCiAgICB5YXhpcyA9IGxpc3QoIHRpdGxlID0gIk51bWVybyBkZSBwYXNhamVyb3MgKG1pbGVzKSIpKQ0KYGBgDQoNCkNvbiBlc3RhIGdyw6FmaWNvIHNlIGNvcnJvYm9yYSBxdWUgZWwgQWVyb3B1ZXJ0byBkZSBMaW1hIChBZXJvcHVlcnRvIEludGVybmFjaW9uYWwgSm9yZ2UgQ2jDoXZleikgZ2VuZXJhIGxhIG1heW9yIGNhbnRpZGFkIGRlIGluZ3Jlc29zIHkgYWRlbcOhcyByZWNpYmUgYSBsYSBtYXlvciBjYW50aWRhZCBkZSBwYXNhamVyb3MgcmVzcGVjdG8gYWwgcmVzdG8gZGVsIFBlcsO6LiBPdHJvcyBhZXJvcHVlcnRvcyBub3RhYmxlcyBzb24gQ3VzY28sIEFyZXF1aXBhIGUgSXF1aXRvcyBkb25kZSBDdXNjbyBlcyBlbCBxdWUgbcOhcyBwYXNhamVyb3MgcmVjaWJlIGZ1ZXJhIGRlIExpbWEuIFNlIHByb2NlZGUgYSBkaWJ1amFyIGVsIG51bWVybyBkZSBwYXNhamVyb3MsIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHkgbG9zIGFlcm9wdWVydG9zLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYseCA9IH5OUC8xMDAwLA0KICAgICAgICB5ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgY29sb3IgPSB+YXMuZmFjdG9yKEFlcm9wdWVydG8pDQogICAgICAgICkNCmBgYA0KDQpFbCBncsOhZmljbyBub3MgZGVqYSBlbiBjbGFybyBsYSBlc3RyZWNoYSByZWxhY2nDs24gZGUgbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIGNvbiBsYSBkZSBpbmdyZXNvcyBxdWUgcG9zZWUgZWwgYWVyb3B1ZXJ0byBkZSBMaW1hIHkgY29tbyBlc3RlIHNvYnJlc2FsZSBwb3IgbXVjaG8gZGVsIHJlc3RvIGRlIGFlcm9wdWVydG9zLiBTZSBjb25jbHV5ZSBxdWUgbG9zIGRhdG9zIGF0w61waWNvcyBwcm92ZW5pZW50ZXMgZGUgaW5ncmVzb3MgdG90YWxlcyBlcmFuIHkgbm9zIGNvbnRhYmFuIHNvYnJlIGxhcyBwZWN1bGlhcmlkYWRlcyBkZWwgY2FzbyBMaW1hLg0KDQojIyBJbmdyZXNvcyBUIFUgVSBBIFRvdGFsIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KU2UgZWxpZ2nDsyBsYSBjb21wYXJhY2nDs24gZGUgbGFzIFQgVSBVIEEsIHBvcnF1ZSBlc3RhIGVzIGxhIFRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPLCBlcyBkZWNpciBlcyB1bmEgdGFyaWZhIHF1ZSBjb21vIGNvbnN1bWlkb3JlcyBkZWJlbW9zIGRlIHBhZ2FyLiBFbCBvYmpldGl2byBhcXXDrSBlcyBhbmFsaXphciBjdWFudG8gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgcHJvdmllbmVuIGRpcmVjdGFtZW50ZSBkZSBsb3MgYm9sc2lsbG9zIGRlIGxvcyBwYXNhamVyb3MuDQoNCmBgYHtyfQ0KcGxvdCgoREYkVFVVQU4vMTAwMDAwMCArIERGJFRVVUFJLzEwMDAwMDApLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MjZjMTUiLCBwY2g9IuKAoiIpDQoNCmBgYA0KDQpDb21lbnphbW9zIGNvbXBhcmFuZG8gZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB0b3RhbGVzLCBzdW1hIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgeSBuYWNpb25hbGVzLCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGUgY2FkYSBhZXJvcHVlcnRvIGVuIGRldGVybWluYWRvIG1lcyB5IGHDsW8gZW4gbWlsbG9uZXMgZGUgZG9sYXJlcy4gQSBzaW1wbGUgdmlzdGEgc2UgcHVlZGUgdmVyIHVuIGNpZXJ0byB0aXBvIGRlIHJlbGFjacOzbiBsaW5lYWwsIHNpbiBlbWJhcmdvIHRlbmVtb3MgcXVlIGNvbXByb2JhcmxvLiBVc2FyZW1vcyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24geWEgcXVlIGVzdGUgbm8gdG9tYSBlbiBjdWVudGEgbGEgZXNjYWxhIGRlIGxhcyB1bmlkYWRlcywgcGVyZmVjdG8gcGFyYSBudWVzdHJvIGVzdHVkaW8uDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiRUVVVBSSArIERGJFRVVUFOLCB1c2U9ImNvbXBsZXRlLm9icyIpDQpgYGANCg0KVGVuZW1vcyB1biBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gcXVlIGVzdGEgbXV5IHByw7N4aW1vIGEgMSwgZXMgZGVjaXIgZXN0YSByZWxhY2nDs24gZXMgY2FzaSBwZXJmZWN0YW1lbnRlIGxpbmVhbCB5IGNvbiB0ZW5kZW5jaWEgYXNjZW5kZW50ZS4NCg0KQWhvcmEgY3JlYXJlbW9zIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3J9DQpUVVVBIDwtIERGJFRVVUFJK0RGJFRVVUFODQptb2RlbG8gPSBsbShERiRJVCB+IFRVVUEsIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj0gKERGJFRVVUFJICsgREYkVFVVQU4pLzEwMDAwMCwgIlkiPURGJElULzEwMDAwMDApDQptb2RlbG8gPSBsbShkJFkgfiBkJFgsIGRhdGE9ZCkNCm1vZGVsbw0KDQpybShkKQ0KYGBgDQoNCkRlbCBtb2RlbG8gY3JlYWRvIHNlIG9idGllbmUgZWwgaW50ZXJjZXB0bywgZXMgZGVjaXIgY3VhbmRvIGxhIFRVVUEgdmFsZHLDoSBjZXJvIHkgbGEgcGVuZGllbnRlLCBlbiBlc3RlIGNhc28gZXMgcmVsYXRpdmFtZW50ZSBiYWphIHBlcm8gYXNjZW5kZW50ZS4NCg0KYGBge3J9DQpwbG90KFRVVUEvMTAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgdG90YWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MjZjMTUiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gMC4xNTU3LCBiPTAuMjE5MCwgY29sPSIjYzlhMjI3IikNCmBgYA0KDQojIyBJbmdyZXNvcyBUVVVBIE5hY2lvbmFsIHkgVFVVQSBJbnRlcm5hY2lvbmFsIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KDQpwbG90KERGJFRVVUFOLzEwMDAwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiSW5ncmVzb3MgVFVVQSBuYWNpb25hbCAobWlsbG9uZXMgZGUgVVMkKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iI2Y4OTYxZSIsIHBjaD0i4oCiIikNCg0KcGxvdChERiRUVVVBSS8xMDAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgaW50ZXJuYWNpb25hbCAobWlsbG9uZXMgZGUgVVMkKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iIzkwYmU2ZCIsIHBjaD0i4oCiIikNCmBgYA0KDQpQcm9iZW1vcyBkZSBudWV2byBhIHVzYXIgZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHBhcmEgYW1iYXMgdmFyaWFibGVzDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiRUVVVBTiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KY29yKERGJElULCBERiRUVVVBSSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkRlIGxvcyBjb2VmaWNpZW50ZXMgZGFkb3Mgc2UgZW5jdWVudHJhIHF1ZToNCg0KLSAgIExvcyBkb3MgY29lZmljaWVudGVzIG11ZXN0cmFuIHVuYSBjYXNpIHBlcmZlY3RhIGxpbmVhbGlkYWQgYXNjZW5kZW50ZS4NCi0gICBOaW5ndW5vIGRlIGxvcyBkb3MgKipjb3IqKiBwb3Igc2VwYXJhZG8gcHVkbyBzdXBlcmFyIGFsIGFudGVyaW9yIHZpc3RvIHByb2R1Y3RvIGRlIGxhIHN1bWEgZGUgbGFzIFRVVUEuDQotICAgRWwgKipjb3IqKiBuYWNpb25hbCBlcyBsaWdlcmFtZW50ZSBzdXBlcmlvciBhbCAqKmNvcioqIGludGVybmFjaW9uYWwuDQoNCkFob3JhIGNvbnN0cnV5YW1vcyBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCBwYXJhIGNhZGEgdW5vLg0KDQpgYGB7cn0NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiRUVVVBTiwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJFRVVUFOLzEwMDAwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiRUVVVBSSwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJFRVVUFJLzEwMDAwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0Kcm0oZCkNCmBgYA0KDQpMb3MgbW9kZWxvcyBwb3NlZW4gYmFzdGFudGVzIGRpZmVyZW5jaWFzIGVudHJlIHPDrSBjb21vIHN1cyBpbnRlcmNlcHRvcyBxdWUgYSBzaW1wbGUgbm8gdGllbmVuIG5hZGEgZW4gY29tw7puIGFsIGlndWFsIHF1ZSBzdXMgcGVuZGllbnRlcy4gVmVhbW9zbG8gZW4gdW5hIGdyYWZpY2EuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCg0KcGxvdChERiRUVVVBTi8xMDAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgbmFjaW9uYWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiNmODk2MWUiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gLTAuMDU5OSwgYj01LjIxMjYsIGNvbD0iI2YzNzIyYyIpDQoNCnBsb3QoREYkVFVVQUkvMTAwMDAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJJbmdyZXNvcyBUVVVBIGludGVybmFjaW9uYWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MGJlNmQiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gMC4zMjk1LCBiPTMuNjg4MiwgY29sPSIjNDNhYThiIikNCg0KYGBgDQoNCkRldGFsbGFtb3MgZW50b25jZXMgcXVlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGd1YXJkYW4gdW5hIGFsdGEgcmVsYWNpw7NuIGNvbiBsb3MgaW5ncmVzb3MgZ2VuZXJhZG9zIHBvciBsYXMgVFVVQSB5IGRlcGVuZGVuIGVuIGdyYW4gbWVkaWRhIGRlIGVzdGFzLCBlcmdvIGxhIGNhbnRpZGFkIGRlIHBhc2FqZXJvcy4NCg0KIyMgUGFuZGVtaWEgdnMgUG9zdFBhbmRlbWlhDQoNCmBgYHtyfQ0KREYyMDIwIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjAiKQ0KREYyMDIxIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjEiKQ0KREYyMDIyIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjIiKQ0KDQpERjIwMjAgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMA0KDQpERjIwMjEgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KREYyMDIyICU+JSBncm91cF9ieShNZXMsQcOxbykgJT4lIHN1bW1hcmlzZShJVCA9IHN1bShJVCwgbmEucm09VFJVRSksIE5QID0gc3VtKE5QLCBuYS5ybSA9IFRSVUUpKSAtPiBERjIwMjINCg0KYGBgDQoNCmBgYHtyfQ0KcGxvdF9seSh5ID0gfkRGMjAyMCRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMCRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIwIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjNTdjYzk5JykNCiAgICAgICAgKSU+JSANCg0KICAgIA0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMSRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIxIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMzhhM2E1JykNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIA0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMiRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMiRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIyIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMjI1NzdhJykNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIA0KICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lc2VzIiksDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIiwNCiAgICBudGlja3MgPSAxMCwNCiAgICByYW5nZSA9IGxpc3QoMCw0NSkpLA0KICAgIA0KICAgIGJhcm1vZGU9Imdyb3VwIikNCmBgYA0KDQpEZWwgZ3LDoWZpY28gZGUgYmFycmFzIHBvZGVtb3Mgb2JzZXJ2YXI6DQoNCi0gICBMYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGVuIGJhc2UgYSBsb3MgbWVzZXMgZGVsIGHDsW8uDQoNCi0gICBFeGlzdGUgdW5hIGFzaW1ldHJpYSBub3RhYmxlIGVudHJlIGxvcyBkYXRvcyBlbiBlbCBhw7FvIDIwMjAuIEVzdGEgYXNpbWV0cmlhIHNlIGV4cGxpY2EgcG9yIGVsIHN1cmdpbWllbnRvIGRlbCBDb3ZpZC0xOS4gTG9zIGluZ3Jlc29zIGJhamFyb24gYmFzdGFudGUgZW4gcHJvcG9yY2nDs24gYSBsYSBtZWRpYS4NCg0KLSAgIFVuIHBhdHLDs24gZGUgY3JlY2ltaWVudG8gc29icmUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGVwZW5kaWVuZG8gZGUgbG9zIG1lc2VzLiBFbiBhbGd1bm9zIG1lc2VzIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHNvbiBlc3BlcmFkbyBhIHNlciBtYXlvcmVzIHF1ZSBlbiBvdHJvcyBtZXNlcywgdW5vIGRlIGxvcyBmYWN0b3JlcyBxdWUgcHVlZGVuIGluZmx1aXIgZW4gZXN0byBzb24gbGFzIHZhY2FjaW9uZXMgcHVlcyBlc3TDoW4gZXN0cmVjaGFtZW50ZSByZWxhY2lvbmFzIGNvbiBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBhIGFib3JkYXJyIGVuIHVuIGFlcm9wdWVydG8uDQoNCmBgYHtyfQ0KDQpwbG90X2x5KCkgJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIwJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIwJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMCIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnIzU3Y2M5OScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjNTdjYzk5JyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDE5NywyMzcsMjExLDAuMyknDQogICAgICAgICklPiUNCiAgICBhZGRfdHJhY2UoREYyMDIxLCB5ID0gfkRGMjAyMSRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjEiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMzOGEzYTUnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzM4YTNhNScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgxMDYsMTY2LDE2OSwwLjMpJw0KICAgICAgICApJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIyJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIyJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMiIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnIzIyNTc3YScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjMjI1NzdhJyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDY4LDEwMiwxMjIsMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lc2VzIiksDQogICAgICAgICAgIHRpdGxlID0gIkV2b2x1dGl2byBJbmdyZXNvcyIsDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIiwgDQogICAgICAgICAgICAgICAgICByYW5nZSA9IGxpc3QoMCw0NSkpDQogICAgKQ0KDQpgYGANCg0KYGBge3J9DQpwbG90X2x5KCkgJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIwJE5QLzEwMDAsDQogICAgICAgIHggPSB+REYyMDIwJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMCIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnI0UwOUYzRScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjRTA5RjNFJyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDIyNSwxODMsMTIzLDAuMyknDQogICAgICAgICklPiUNCiAgICBhZGRfdHJhY2UoREYyMDIxLCB5ID0gfkRGMjAyMSROUC8xMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjEiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM5RTJBMkInKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzlFMkEyQicpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgxNTgsNzIsNzQsMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMiROUC8xMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMiRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM1NDBCMEUnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzU0MEIwRScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSg4Nyw0NSw0NywwLjMpJw0KICAgICAgICApJT4lDQogICAgDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiTWVzZXMiKSwNCiAgICAgICAgICAgdGl0bGUgPSAiRXZvbHV0aXZvIFBhc2FqZXJvcyIsDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJOdW1lcm8gZGUgUGFzYWplcm9zIChNaWxlcykiKSkNCmBgYA0KDQpEZSBsb3MgZ3LDoWZpY29zIGV2b2x1dGl2b3MgcG9kZW1vcyBhcHJlY2lhcjoNCg0KLSAgIENvbW8gZXMgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZnJlbnRlIGEgbG9zIG1lc2VzIHkgYSBsb3MgYcOxb3MgbWFyY2Fkb3MgcG9yIGxhIHBhbmRlbWlhLg0KDQotICAgRW4gZWwgbWVzIGRlIEZlYnJlcm8gZGVsIGHDsW8gMjAyMCBjb21pZW56YSB1bmEgY2HDrWRhIGRyw6FzdGljYSBlbiBsb3MgaW5ncmVzb3MgaGFzdGEgQWJyaWwgZGVsIG1pc21vIGHDsW8gZG9uZGUgY29taWVuemEgYSBlc3RhYmlsaXphcnNlLiBFc3RlIHBlcmlvZG8gY29pbmNpZGUgY29uIGxhIGFwYXJpY2nDs24gZGVsIENvdmlkLTE5IGVuIFBlcsO6IHkgZWwgZXN0YWJsZWNpbWllbnRvIGRlIGxhcyBtZWRpZGFzIGRlIGNvbmZpbmFtaWVudG8uIEVsIGNvbmZpbmFtaWVudG8gaW5kaWNhIHF1ZSBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBzZSByZWR1Y2UgZW4gZ3JhbiBwcm9wb3JjacOzbi4gRXN0YSBjYXVzYSB0YW1iacOpbiBzZSBwdWVkZSBvYnNlcnZhciBlbiBlbCBldm9sdXRpdm8gZGUgcGFzYWplcm9zIHkgZWwgY29tbyBzdSBuw7ptZXJvIGRlIGNhZSBoYXN0YSAwIG8gY2FzaSAwLiBMb3MgYWVyb3B1ZXJ0byB0dXZpZXJvbiBjb25zZWN1ZW5jaWFzIHF1ZSB0YXJkYXJvbiBtdWNobyBlbiBkaXNpcGFyc2UgTXVlc3RyYSBkZSBlbGxvIGVzIGNvbW8gc2UgdGFyZMOzIDIgYcOxb3MgeSA1IG1lc2VzIHBhcmEgdm9sdmVyIGEgdW4gcHVudG8gc2ltaWxhciBhbCBkZSBGZWJyZXJvIDIwMjAgZW4gaW5ncmVzb3MgdG90YWxlcy4NCg0KICAgIGBgYHtyfQ0KDQogICAgcm91bmQoMTAwIC0gKChmaWx0ZXIoREYyMDIwLCBNZXMgPT0gIkFicmlsIikkSVQvMTAwMDAwMCApLyggZmlsdGVyKERGMjAyMCwgTWVzID09ICJGZWJyZXJvIikkSVQvMTAwMDAwMCkgKiAxMDApICwyKQ0KDQogICAgcm91bmQoIC0gZmlsdGVyKERGMjAyMCwgTWVzID09ICJBYnJpbCIpJElULzEwMDAwMDAgICsgZmlsdGVyKERGMjAyMCxNZXMgPT0gIkZlYnJlcm8iKSRJVC8xMDAwMDAwLCAyKQ0KICAgIGBgYA0KDQotICAgTGEgcMOpcmRpZGEgZGVsIG1lcyBkZSBBYnJpbCBkZWwgMjAyMCByZXNwZWN0byBhbCBtZXMgZGUgRmVicmVybyBkZWwgMjAyMCBmdWUgZGVsIDg2LjY4JSBzdXBvbmllbmRvIHVuYSBkaWZlcmVuY2lhIGRlIDMxLjc2IG1pbGxvbmVzIGRlIGRvbGFyZXMuDQoNCi0gICBBIHBhcnRpciBkZWwgbWVzIGRlIEFicmlsIHNlIGVzdGFiaWxpemFuIGxvcyBpbmdyZXNvcyBkZWwgYcOxbyAyMDIwLiBFc3RvcyBzb24gYmFqb3MgcGVybyBzZSBvYnNlcnZhIHVuYSB0ZW5kZW5jaWEgYXNjZW5kZW50ZS4gVGVuZGVuY2lhIHF1ZSBjb250aW51YSBlbiBsb3MgYcOxb3MgMjAyMSB5IDIwMjIgYSBtZWRpZGEgcXVlIGVsIGNvbmZpbmFtaWVudG8gc2UgbGV2YW50YSwgbGEgcGFuZGVtaWEgc2UgY29udHJvbGEgeSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIGF1bWVudGEuDQoNCiMjIENvbmNsdXNpw7NuDQoNCkEgcmF6w7NuIGRlIHJlc3VtZW4sIGVuIG51ZXN0cm8gYW7DoWxpc2lzIHNvYnJlIGxhIHJlbGFjacOzbiBlbnRyZSBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyB5IGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGxvcyBhZXJvcHVlcnRvcyBncmFmaWNhbW9zIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMsIGxhcyBkaWZlcmVudGVzIHJlbGFjaW9uZXMgZW50cmUgdmFyaWFibGVzIHRhbGVzIGNvbW8gbGEgw7psdGltYSB2aXN0YSAoSW5ncmVzb3MgVFVVQSB2cyBJbmdyZXNvcyBUb3RhbGVzKSwgKGNhbnRpZGFkIGRlIHBhc2FqZXJvcyB5IGFlcm9wdWVydG9zKS4gQXNpbWlzbW8gb2JzZXJ2YW1vcyB5IGRlc2NyaWJpbW9zIGVsIGNvbXBvcnRhbWllbnRvIGV2b2x1dGl2byBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyByZXNwZWN0byBhIGxvcyBhw7FvcyB2aXZpZG9zIGVuIHBhbmRlbWlhIHkgcG9zdC1wYW5kZW1pYS4gRmluYWxlbW50ZSwgY29uIGxhIGluZm9ybWFjacOzbiByZWNvbGVjdGFkYSB5IGVsIGVzdHVkaW8gcmVhbGl6YWRvIHNlIGVuY29udHLDsyBxdWUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZ2VuZXJhZG9zIHBvciBsb3MgYWVyb3B1ZXJ0b3MgZW4gZWwgUGVyw7ogZGVwZW5kZW50ZSBhbHRhbWVudGUgZW4gbG9zIGNvbnN1bWlkb3JlcyBvIHBhc2FqZXJvcywgc2llbmRvIGxhIFRVVUEgZWwgZWplbXBsbyBtw6FzIGNsYXJvIGRlIGVsbG8uDQo=